diff --git a/api/src/main/java/org/jfrog/artifactory/client/model/repository/settings/HuggingFaceRepositorySettings.java b/api/src/main/java/org/jfrog/artifactory/client/model/repository/settings/HuggingFaceRepositorySettings.java new file mode 100644 index 00000000..5760bde8 --- /dev/null +++ b/api/src/main/java/org/jfrog/artifactory/client/model/repository/settings/HuggingFaceRepositorySettings.java @@ -0,0 +1,7 @@ +package org.jfrog.artifactory.client.model.repository.settings; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public interface HuggingFaceRepositorySettings extends RepositorySettings { +} diff --git a/build.gradle b/build.gradle index 2487c982..35ebaaaf 100644 --- a/build.gradle +++ b/build.gradle @@ -64,23 +64,30 @@ subprojects { // Force secure versions to fix vulnerabilities configurations.all { resolutionStrategy { - // Use latest confirmed available Jetty 9.4.x versions - force 'org.eclipse.jetty:jetty-server:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-servlets:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-http:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-util:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-io:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-client:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-security:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-servlet:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-webapp:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-proxy:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-continuation:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-util-ajax:9.4.56.v20240826' - force 'org.eclipse.jetty:jetty-xml:9.4.56.v20240826' - force 'org.eclipse.jetty.http2:http2-server:9.4.56.v20240826' - force 'org.eclipse.jetty.http2:http2-common:9.4.56.v20240826' - force 'org.eclipse.jetty.http2:http2-hpack:9.4.56.v20240826' + // Use latest confirmed available Jetty 9.4.x versions - consistent versions + force 'org.eclipse.jetty:jetty-server:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-servlets:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-http:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-util:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-io:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-client:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-security:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-servlet:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-webapp:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-proxy:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-continuation:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-util-ajax:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-xml:9.4.58.v20250814' + force 'org.eclipse.jetty.http2:http2-server:9.4.58.v20250814' + force 'org.eclipse.jetty.http2:http2-common:9.4.58.v20250814' + force 'org.eclipse.jetty.http2:http2-hpack:9.4.58.v20250814' + // Force ALPN modules that wiremock depends on + force 'org.eclipse.jetty:jetty-alpn-server:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-alpn-java-server:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-alpn-openjdk8-server:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-alpn-java-client:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-alpn-openjdk8-client:9.4.58.v20250814' + force 'org.eclipse.jetty:jetty-alpn-client:9.4.58.v20250814' // Latest secure versions force 'commons-io:commons-io:2.18.0' force 'net.minidev:json-smart:2.5.2' diff --git a/services/build.gradle b/services/build.gradle index 86500c2f..be76d9c8 100644 --- a/services/build.gradle +++ b/services/build.gradle @@ -42,4 +42,4 @@ artifacts { archives sourcesJar, javadocJar, jar -} +} \ No newline at end of file diff --git a/services/src/main/java/org/jfrog/artifactory/client/impl/jackson/RepositorySettingsMixIn.java b/services/src/main/java/org/jfrog/artifactory/client/impl/jackson/RepositorySettingsMixIn.java index 91d20b2f..7ee7c604 100644 --- a/services/src/main/java/org/jfrog/artifactory/client/impl/jackson/RepositorySettingsMixIn.java +++ b/services/src/main/java/org/jfrog/artifactory/client/impl/jackson/RepositorySettingsMixIn.java @@ -45,7 +45,8 @@ @JsonSubTypes.Type(value = GoRepositorySettingsImpl.class, name = "go"), @JsonSubTypes.Type(value = CargoRepositorySettingsImpl.class, name = "cargo"), @JsonSubTypes.Type(value = TerraformRepositorySettingsImpl.class, name = "terraform"), - @JsonSubTypes.Type(value = OciRepositorySettingsImpl.class, name = "oci") + @JsonSubTypes.Type(value = OciRepositorySettingsImpl.class, name = "oci"), + @JsonSubTypes.Type(value = HuggingFaceRepositorySettingsImpl.class, name = "huggingfaceml") }) public abstract class RepositorySettingsMixIn { diff --git a/services/src/main/java/org/jfrog/artifactory/client/model/impl/FederatedRepositoryBuilderImpl.java b/services/src/main/java/org/jfrog/artifactory/client/model/impl/FederatedRepositoryBuilderImpl.java index 36bb7ea8..9098f4ac 100644 --- a/services/src/main/java/org/jfrog/artifactory/client/model/impl/FederatedRepositoryBuilderImpl.java +++ b/services/src/main/java/org/jfrog/artifactory/client/model/impl/FederatedRepositoryBuilderImpl.java @@ -16,7 +16,7 @@ */ public class FederatedRepositoryBuilderImpl extends NonVirtualRepositoryBuilderBase implements FederatedRepositoryBuilder { private static Set federatedRepositorySupportedTypes = new HashSet<>(Arrays.asList( - bower, cocoapods, cran, conda, debian, docker, gems, generic, gitlfs, gradle, ivy, maven, npm, nuget, opkg, pypi, sbt, vagrant, yum, rpm, composer, conan, chef, puppet, helm, helmoci, go, cargo, terraform, oci + bower, cocoapods, cran, conda, debian, docker, gems, generic, gitlfs, gradle, ivy, maven, npm, nuget, opkg, pypi, sbt, vagrant, yum, rpm, composer, conan, chef, puppet, helm, helmoci, go, cargo, terraform, oci, huggingfaceml )); protected List members = new ArrayList<>(); diff --git a/services/src/main/java/org/jfrog/artifactory/client/model/impl/LocalRepositoryBuilderImpl.java b/services/src/main/java/org/jfrog/artifactory/client/model/impl/LocalRepositoryBuilderImpl.java index 2e69ee3c..3e0debcc 100644 --- a/services/src/main/java/org/jfrog/artifactory/client/model/impl/LocalRepositoryBuilderImpl.java +++ b/services/src/main/java/org/jfrog/artifactory/client/model/impl/LocalRepositoryBuilderImpl.java @@ -17,7 +17,7 @@ */ public class LocalRepositoryBuilderImpl extends NonVirtualRepositoryBuilderBase implements LocalRepositoryBuilder { private static Set localRepositorySupportedTypes = new HashSet(Arrays.asList( - bower, cocoapods, cran, conda, debian, docker, gems, generic, gitlfs, gradle, ivy, maven, npm, nuget, opkg, pypi, sbt, vagrant, yum, rpm, composer, conan, chef, puppet, helm, helmoci, go, cargo, terraform, oci + bower, cocoapods, cran, conda, debian, docker, gems, generic, gitlfs, gradle, ivy, maven, npm, nuget, opkg, pypi, sbt, vagrant, yum, rpm, composer, conan, chef, puppet, helm, helmoci, go, cargo, terraform, oci, huggingfaceml )); protected LocalRepositoryBuilderImpl() { diff --git a/services/src/main/java/org/jfrog/artifactory/client/model/impl/PackageTypeImpl.java b/services/src/main/java/org/jfrog/artifactory/client/model/impl/PackageTypeImpl.java index 7011ff4c..a5e7dab8 100644 --- a/services/src/main/java/org/jfrog/artifactory/client/model/impl/PackageTypeImpl.java +++ b/services/src/main/java/org/jfrog/artifactory/client/model/impl/PackageTypeImpl.java @@ -35,7 +35,8 @@ public enum PackageTypeImpl implements PackageType { go, cargo, terraform, - oci; + oci, + huggingfaceml; @Override public boolean isCustom() { diff --git a/services/src/main/java/org/jfrog/artifactory/client/model/impl/RemoteRepositoryBuilderImpl.java b/services/src/main/java/org/jfrog/artifactory/client/model/impl/RemoteRepositoryBuilderImpl.java index b4c06cd4..a49a9b26 100644 --- a/services/src/main/java/org/jfrog/artifactory/client/model/impl/RemoteRepositoryBuilderImpl.java +++ b/services/src/main/java/org/jfrog/artifactory/client/model/impl/RemoteRepositoryBuilderImpl.java @@ -17,7 +17,7 @@ */ public class RemoteRepositoryBuilderImpl extends NonVirtualRepositoryBuilderBase implements RemoteRepositoryBuilder { private static Set remoteRepositorySupportedTypes = new HashSet(Arrays.asList( - bower, cocoapods, cran, conda, debian, docker, gems, generic, gitlfs, gradle, ivy, maven, npm, nuget, opkg, p2, pypi, sbt, vcs, yum, rpm, composer, conan, chef, puppet, helm, helmoci, go, cargo, terraform, oci + bower, cocoapods, cran, conda, debian, docker, gems, generic, gitlfs, gradle, ivy, maven, npm, nuget, opkg, p2, pypi, sbt, vcs, yum, rpm, composer, conan, chef, puppet, helm, helmoci, go, cargo, terraform, oci, huggingfaceml )); private String url; diff --git a/services/src/main/java/org/jfrog/artifactory/client/model/impl/VirtualRepositoryBuilderImpl.java b/services/src/main/java/org/jfrog/artifactory/client/model/impl/VirtualRepositoryBuilderImpl.java index 0f3d388b..e025dd4c 100644 --- a/services/src/main/java/org/jfrog/artifactory/client/model/impl/VirtualRepositoryBuilderImpl.java +++ b/services/src/main/java/org/jfrog/artifactory/client/model/impl/VirtualRepositoryBuilderImpl.java @@ -15,7 +15,7 @@ */ public class VirtualRepositoryBuilderImpl extends RepositoryBuilderBase implements VirtualRepositoryBuilder { private static Set virtualRepositorySupportedTypes = new HashSet(Arrays.asList( - bower, cran, conda, docker, debian, gems, generic, gitlfs, gradle, ivy, maven, npm, nuget, p2, pypi, sbt, yum, rpm, composer, conan, chef, puppet, helm, helmoci, go, terraform, oci + bower, cran, conda, docker, debian, gems, generic, gitlfs, gradle, ivy, maven, npm, nuget, p2, pypi, sbt, yum, rpm, composer, conan, chef, puppet, helm, helmoci, go, terraform, oci, huggingfaceml )); private Collection repositories = Collections.emptyList(); diff --git a/services/src/main/java/org/jfrog/artifactory/client/model/repository/settings/impl/HuggingFaceRepositorySettingsImpl.java b/services/src/main/java/org/jfrog/artifactory/client/model/repository/settings/impl/HuggingFaceRepositorySettingsImpl.java new file mode 100644 index 00000000..d900aa24 --- /dev/null +++ b/services/src/main/java/org/jfrog/artifactory/client/model/repository/settings/impl/HuggingFaceRepositorySettingsImpl.java @@ -0,0 +1,30 @@ +package org.jfrog.artifactory.client.model.repository.settings.impl; + +import org.jfrog.artifactory.client.model.PackageType; +import org.jfrog.artifactory.client.model.impl.PackageTypeImpl; +import org.jfrog.artifactory.client.model.repository.settings.AbstractRepositorySettings; +import org.jfrog.artifactory.client.model.repository.settings.HuggingFaceRepositorySettings; + +public class HuggingFaceRepositorySettingsImpl extends AbstractRepositorySettings implements HuggingFaceRepositorySettings { + public static String defaultLayout = "simple-default"; + + public HuggingFaceRepositorySettingsImpl() { + super(defaultLayout); + } + + @Override + public PackageType getPackageType() { + return PackageTypeImpl.huggingfaceml; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + return o instanceof HuggingFaceRepositorySettingsImpl; + } + + @Override + public int hashCode() { + return super.hashCode(); + } +} diff --git a/services/src/test/groovy/org/jfrog/artifactory/client/HuggingFacePackageTypeRepositoryTest.java b/services/src/test/groovy/org/jfrog/artifactory/client/HuggingFacePackageTypeRepositoryTest.java new file mode 100644 index 00000000..fdd1b851 --- /dev/null +++ b/services/src/test/groovy/org/jfrog/artifactory/client/HuggingFacePackageTypeRepositoryTest.java @@ -0,0 +1,78 @@ +package org.jfrog.artifactory.client; + +import org.jfrog.artifactory.client.model.Repository; +import org.jfrog.artifactory.client.model.RepositoryType; +import org.jfrog.artifactory.client.model.builder.RepositoryBuilders; +import org.jfrog.artifactory.client.model.impl.PackageTypeImpl; +import org.jfrog.artifactory.client.model.repository.settings.HuggingFaceRepositorySettings; +import org.jfrog.artifactory.client.model.repository.settings.RepositorySettings; +import org.jfrog.artifactory.client.model.repository.settings.impl.HuggingFaceRepositorySettingsImpl; +import org.testng.annotations.AfterMethod; +import org.testng.SkipException; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +public class HuggingFacePackageTypeRepositoryTest extends BaseRepositoryTests { + + private final String localRepo = "huggingface-local-1"; + private final String federatedRepo = "huggingface-federated-1"; + private final String virtualRepo = "huggingface-virtual-1"; + + @BeforeMethod + @AfterMethod + private void cleanup() { + deleteRepoIfExists(localRepo); + deleteRepoIfExists(federatedRepo); + deleteRepoIfExists(virtualRepo); + } + + @Override + public RepositorySettings getRepositorySettings(RepositoryType repositoryType) { + return new HuggingFaceRepositorySettingsImpl(); + } + + @Test + public void testHuggingFaceLocalRepo() { + HuggingFaceRepositorySettings settings = new HuggingFaceRepositorySettingsImpl(); + RepositoryBuilders repositoryBuilders = artifactory.repositories().builders(); + Repository localRepository = repositoryBuilders.localRepositoryBuilder() + .key(localRepo) + .description("new local huggingface repo") + .notes("some notes") + .repositorySettings(settings) + .build(); + + // Use position 0 for create, as required by the interface + String localCreateResult = artifactory.repositories().create(0, localRepository); + Repository localRepoFromServer = artifactory.repository(localRepo).get(); + + assertNotNull(localRepoFromServer); + assertEquals(localRepoFromServer.getKey(), localRepo); + assertEquals(localRepoFromServer.getDescription(), "new local huggingface repo"); + assertEquals(localRepoFromServer.getNotes(), "some notes"); + assertEquals(localRepoFromServer.getRepoLayoutRef(), "simple-default"); + assertEquals(localRepoFromServer.getRepositorySettings().getPackageType(), PackageTypeImpl.huggingfaceml); + } + + @Test + public void testHuggingFaceFederatedRepo() { + HuggingFaceRepositorySettings settings = new HuggingFaceRepositorySettingsImpl(); + RepositoryBuilders repositoryBuilders = artifactory.repositories().builders(); + Repository federatedRepository = repositoryBuilders.federatedRepositoryBuilder() + .key(federatedRepo) + .description("new federated huggingface repo") + .notes("some notes") + .repositorySettings(settings) + .build(); + + String federatedCreateResult = artifactory.repositories().create(0, federatedRepository); + Repository federatedRepoFromServer = artifactory.repository(federatedRepo).get(); + assertNotNull(federatedRepoFromServer); + assertEquals(federatedRepoFromServer.getKey(), federatedRepo); + assertEquals(federatedRepoFromServer.getDescription(), "new federated huggingface repo"); + assertEquals(federatedRepoFromServer.getNotes(), "some notes"); + } +} diff --git a/services/src/test/groovy/org/jfrog/artifactory/client/HuggingFaceRepositorySettingsTest.java b/services/src/test/groovy/org/jfrog/artifactory/client/HuggingFaceRepositorySettingsTest.java new file mode 100644 index 00000000..d258ce2b --- /dev/null +++ b/services/src/test/groovy/org/jfrog/artifactory/client/HuggingFaceRepositorySettingsTest.java @@ -0,0 +1,45 @@ +package org.jfrog.artifactory.client; + +import org.jfrog.artifactory.client.model.PackageType; +import org.jfrog.artifactory.client.model.impl.PackageTypeImpl; +import org.jfrog.artifactory.client.model.repository.settings.impl.HuggingFaceRepositorySettingsImpl; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +/** + * Test for HuggingFace repository settings implementation + */ +public class HuggingFaceRepositorySettingsTest { + + @Test + public void testHuggingFaceRepositorySettings() { + HuggingFaceRepositorySettingsImpl settings = new HuggingFaceRepositorySettingsImpl(); + + // Test package type + PackageType packageType = settings.getPackageType(); + assertEquals(packageType, PackageTypeImpl.huggingfaceml); + + // Test default layout + assertEquals(settings.getRepoLayout(), "simple-default"); + + // Test layout setting + settings.setRepoLayout("custom-layout"); + assertEquals(settings.getRepoLayout(), "custom-layout"); + + // Test that it's not a custom package type + assertFalse(packageType.isCustom()); + } + + @Test + public void testConsistencyWithOtherPackageManagers() { + HuggingFaceRepositorySettingsImpl huggingFaceSettings = new HuggingFaceRepositorySettingsImpl(); + + // Verify it follows the same interface pattern as other package managers + assertNotNull(huggingFaceSettings.getPackageType()); + assertNotNull(huggingFaceSettings.getRepoLayout()); + + // Test that the default layout is properly set + assertEquals(HuggingFaceRepositorySettingsImpl.defaultLayout, "simple-default"); + } +}