diff --git a/CHANGELOG.md b/CHANGELOG.md
index fcbf446..7a02695 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,9 @@
### Added
- Spotless gradle plugin to format code
+### Changed
+- [#40](https://github.com/devatherock/artifactory-badge/issues/40): To not treat `_uploads` subfolder as a docker tag
+
### Removed
- Custom environment variables with `LOGGING_LEVEL` prefix and updated documentation to use environment variables
with `LOGGER_LEVELS` prefix supported out of the box by micronaut
diff --git a/README.md b/README.md
index 7c78be2..c54e5c4 100644
--- a/README.md
+++ b/README.md
@@ -24,10 +24,11 @@ docker run --rm \
|---------------------------------------|--------------|------------------|-----------------------------------------------------------------------------------|
| ARTIFACTORY_URL | true | (None) | The JFrog artifactory URL that hosts the docker registry |
| ARTIFACTORY_API_KEY | true | (None) | API key for interacting with artifactory's REST API |
-| ARTIFACTORY_BADGE_SHIELDS_IO_ENABLED | false | true | Indicates if shields.io should be used to generate the badge |
-| LOGGING_LEVEL_ROOT | false | INFO | [SLF4J](http://www.slf4j.org/api/org/apache/commons/logging/Log.html) log level, for all(framework and custom) code |
-| LOGGING_LEVEL_IO_GITHUB_DEVATHEROCK | false | INFO | [SLF4J](http://www.slf4j.org/api/org/apache/commons/logging/Log.html) log level, for custom code |
-| MICRONAUT_ENVIRONMENTS | false | (None) | Setting the value to `mock` will mock the calls to the artifactory. Only for testing purposes |
+| ARTIFACTORY_EXCLUDED_FOLDERS | false | /_uploads | Subfolders to be not treated as docker tags |
+| ARTIFACTORY_BADGE_SHIELDS_IO_ENABLED | false | true | Indicates if shields.io should be used to generate the badge |
+| LOGGER_LEVELS_ROOT | false | INFO | [SLF4J](http://www.slf4j.org/api/org/apache/commons/logging/Log.html) log level, for all(framework and custom) code |
+| LOGGER_LEVELS_IO_GITHUB_DEVATHEROCK | false | INFO | [SLF4J](http://www.slf4j.org/api/org/apache/commons/logging/Log.html) log level, for custom code |
+| MICRONAUT_ENVIRONMENTS | false | (None) | Setting the value to `local` will mock the calls to the artifactory. Only for testing purposes |
| MICRONAUT_SERVER_PORT | false | 8080 | Port in which the app listens on |
| JAVA_OPTS | false | (None) | Additional JVM arguments to be passed to the container's java process |
diff --git a/build.gradle b/build.gradle
index 727037b..2c8eea9 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,13 +1,12 @@
plugins {
- id "net.ltgt.apt-eclipse" version "0.21"
id "com.github.johnrengelman.shadow" version "6.1.0"
- id "application"
+ id 'io.micronaut.application' version '1.4.4'
id 'java'
id 'groovy'
id 'jacoco'
id 'org.sonarqube' version '3.1.1'
id 'com.github.kt3k.coveralls' version '2.12.0'
- id 'com.diffplug.spotless' version '5.12.0'
+ id 'com.diffplug.spotless' version '5.12.1'
}
version "0.4.0"
diff --git a/src/main/java/io/github/devatherock/artifactory/config/ArtifactoryProperties.java b/src/main/java/io/github/devatherock/artifactory/config/ArtifactoryProperties.java
index 42782fd..b4a6ba6 100644
--- a/src/main/java/io/github/devatherock/artifactory/config/ArtifactoryProperties.java
+++ b/src/main/java/io/github/devatherock/artifactory/config/ArtifactoryProperties.java
@@ -1,5 +1,9 @@
package io.github.devatherock.artifactory.config;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import javax.annotation.PostConstruct;
import javax.validation.constraints.NotBlank;
@@ -9,6 +13,12 @@
import lombok.Getter;
import lombok.Setter;
+/**
+ * Configurable properties for the application
+ *
+ * @author devaprasadh
+ *
+ */
@Getter
@Setter
@Context
@@ -32,6 +42,11 @@ public class ArtifactoryProperties {
@Setter(AccessLevel.NONE)
private String storageUrlPrefix;
+ /**
+ * Subfolders to be not treated as docker tags
+ */
+ private List excludedFolders = new ArrayList<>(Arrays.asList("/_uploads"));
+
@PostConstruct
public void init() {
urlPrefix = url + "/artifactory/";
diff --git a/src/main/java/io/github/devatherock/artifactory/service/DockerBadgeService.java b/src/main/java/io/github/devatherock/artifactory/service/DockerBadgeService.java
index 26cd005..1dcbe59 100644
--- a/src/main/java/io/github/devatherock/artifactory/service/DockerBadgeService.java
+++ b/src/main/java/io/github/devatherock/artifactory/service/DockerBadgeService.java
@@ -1,10 +1,7 @@
package io.github.devatherock.artifactory.service;
-import java.text.DecimalFormat;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
-import java.util.HashMap;
-import java.util.Map;
import java.util.regex.Pattern;
import javax.inject.Singleton;
@@ -41,8 +38,6 @@ public class DockerBadgeService {
private static final double BYTES_IN_MB = 1024d * 1024;
private static final String FILE_NAME_MANIFEST = "/manifest.json";
private static final String HDR_API_KEY = "X-JFrog-Art-Api";
- private static final double PULLS_REDUCER = 1000;
- private static final int MAX_REDUCTIONS = 3;
/**
* Constant for sort by semantic version
@@ -52,18 +47,6 @@ public class DockerBadgeService {
* Major version part of a semantic version
*/
private static final String VERSION_PART_MAJOR = "major";
- /**
- * Minor version part of a semantic version
- */
- private static final String VERSION_PART_MINOR = "minor";
- /**
- * Patch version part of a semantic version
- */
- private static final String VERSION_PART_PATCH = "patch";
- /**
- * Map containing suffixes for download count
- */
- private static final Map PULLS_SUFFIX = new HashMap<>();
/**
* Formatter to parse dates like {@code 2020-10-01T00:00:00.000Z}
*/
@@ -74,17 +57,6 @@ public class DockerBadgeService {
*/
private static final Pattern PTRN_NUMERIC_VERSION = Pattern.compile(
"^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))*(\\-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$");
- /**
- * Pattern to match numbers
- */
- private static final Pattern PTRN_NUMBER = Pattern.compile("^[0-9]+$");
-
- static {
- PULLS_SUFFIX.put(0, "");
- PULLS_SUFFIX.put(1, "k");
- PULLS_SUFFIX.put(2, "M");
- PULLS_SUFFIX.put(3, "G");
- }
private final BlockingHttpClient artifactoryClient;
private final BadgeGenerator badgeGenerator;
@@ -100,7 +72,8 @@ public String getImageSizeBadge(String packageName, String tag, String badgeLabe
.reduce((totalSize, currentLayerSize) -> totalSize + currentLayerSize).get() / BYTES_IN_MB;
LOGGER.info("Size of {}/{}: {} MB", packageName, tag, imageSize);
- return badgeGenerator.generateBadge(badgeLabel, String.format("%s MB", formatDecimal(imageSize, "0.##")));
+ return badgeGenerator.generateBadge(badgeLabel,
+ String.format("%s MB", DockerBadgeServiceHelper.formatDecimal(imageSize, "0.##")));
} else {
return generateNotFoundBadge(badgeLabel);
}
@@ -128,7 +101,7 @@ public String getPullsCountBadge(String packageName, String badgeLabel) {
long downloadCount = 0;
for (ArtifactoryFolderElement child : folderInfo.getChildren()) {
- if (child.isFolder()) {
+ if (isTag(child)) {
ArtifactoryFileStats fileStats = getManifestStats(packageName, child.getUri());
if (null != fileStats) {
@@ -137,7 +110,8 @@ public String getPullsCountBadge(String packageName, String badgeLabel) {
}
}
LOGGER.info("Download count of {}: {}", packageName, downloadCount);
- return badgeGenerator.generateBadge(badgeLabel, formatDownloadCount(downloadCount));
+ return badgeGenerator.generateBadge(badgeLabel,
+ DockerBadgeServiceHelper.formatDownloadCount(downloadCount));
} else {
return generateNotFoundBadge(badgeLabel);
}
@@ -160,7 +134,7 @@ public String getLatestVersionBadge(String packageName, String badgeLabel, Strin
ArtifactoryFolderInfo latestVersion = null;
for (ArtifactoryFolderElement child : folderInfo.getChildren()) {
- if (child.isFolder()) {
+ if (isTag(child)) {
if (SORT_TYPE_SEMVER.equals(sortType)) {
// Substring to remove the leading slash
String currentVersion = child.getUri().substring(1);
@@ -170,7 +144,8 @@ public String getLatestVersionBadge(String packageName, String badgeLabel, Strin
latestVersion = ArtifactoryFolderInfo.builder().path(child.getUri()).build();
} else {
// Substring to remove the leading slash
- int result = compareVersions(latestVersion.getPath().substring(1), currentVersion,
+ int result = DockerBadgeServiceHelper.compareVersions(
+ latestVersion.getPath().substring(1), currentVersion,
VERSION_PART_MAJOR);
if (result == -1) {
latestVersion = ArtifactoryFolderInfo.builder().path(child.getUri()).build();
@@ -178,6 +153,8 @@ public String getLatestVersionBadge(String packageName, String badgeLabel, Strin
}
}
} else {
+ // Find the modified time of each subfolder - each subfolder corresponds to a
+ // tag
ArtifactoryFolderInfo currentVersion = getArtifactoryFolderInfo(packageName + child.getUri());
if (null == latestVersion || (null != currentVersion
@@ -192,7 +169,8 @@ public String getLatestVersionBadge(String packageName, String badgeLabel, Strin
if (null != latestVersion) {
LOGGER.info("Latest version of {}: {}", packageName, latestVersion.getPath());
- return badgeGenerator.generateBadge(badgeLabel, getVersionBadgeValue(latestVersion));
+ return badgeGenerator.generateBadge(badgeLabel,
+ DockerBadgeServiceHelper.getVersionBadgeValue(latestVersion));
} else {
return generateNotFoundBadge(badgeLabel);
}
@@ -280,110 +258,12 @@ private String generateNotFoundBadge(String badgeLabel) {
}
/**
- * Compares two versions
- *
- * @param versionOne
- * @param versionTwo
- * @param versionPartType
- * @return {@literal -1} if {@code versionTwo} greater than {@code versionOne},
- * {@literal 1} otherwise
- */
- private int compareVersions(String versionOne, String versionTwo, String versionPartType) {
- int result = 0;
-
- int versionPartEndOne = getVersionPartEndIndex(versionOne);
- String versionPartOneText = versionOne.substring(0,
- versionPartEndOne != -1 ? versionPartEndOne : versionOne.length());
- long versionPartOne = readVersionAsNumber(versionPartOneText);
- int versionPartEndTwo = getVersionPartEndIndex(versionTwo);
- String versionPartTwoText = versionTwo.substring(0,
- versionPartEndTwo != -1 ? versionPartEndTwo : versionTwo.length());
- long versionPartTwo = readVersionAsNumber(versionPartTwoText);
-
- if (versionPartOne > versionPartTwo) {
- result = 1;
- } else if (versionPartOne < versionPartTwo) {
- result = -1;
- } else {
- if ((versionPartOneText.length() + 1) >= versionOne.length()) {
- if ((versionPartTwoText.length() + 1) < versionTwo.length()) {
- result = -1;
- }
- } else if ((versionPartTwoText.length() + 1) < versionTwo.length()) {
- if (!VERSION_PART_PATCH.equals(versionPartType)) {
- result = compareVersions(versionOne.substring(versionPartEndOne + 1),
- versionTwo.substring(versionPartEndTwo + 1),
- VERSION_PART_MAJOR.equals(versionPartType) ? VERSION_PART_MINOR : VERSION_PART_PATCH);
- }
- } else {
- result = 1;
- }
- }
-
- return result;
- }
-
- /**
- * Returns the index at which the first version part ends
- *
- * @param version
- * @return the index
+ * Checks if the supplied artifactory folder content corresponds to a tag
+ *
+ * @param child
+ * @return a flag
*/
- private int getVersionPartEndIndex(String version) {
- return version.indexOf('.') != -1 ? version.indexOf('.') : version.indexOf('-');
- }
-
- /**
- * Converts version string into a number
- *
- * @param version
- * @return the version as number
- */
- private long readVersionAsNumber(String version) {
- return PTRN_NUMBER.matcher(version).matches() ? Long.parseLong(version) : 0;
- }
-
- /**
- * Returns the formatted value to be displayed in the version badge
- *
- * @param version
- * @return the version badge value
- */
- private String getVersionBadgeValue(ArtifactoryFolderInfo version) {
- String versionValue = version.getPath().substring(version.getPath().lastIndexOf('/') + 1);
-
- // Append v prefix if version is numeric or a semantic version
- return PTRN_NUMERIC_VERSION.matcher(versionValue).matches() ? 'v' + versionValue : versionValue;
- }
-
- /**
- * Formats a decimal number into a string
- *
- * @param inputDecimal the decimal number to format
- * @param format the pattern to which to format to
- * @return a formatted string
- */
- private String formatDecimal(double inputDecimal, String format) {
- DecimalFormat decimalFormat = new DecimalFormat(format);
- decimalFormat.setDecimalSeparatorAlwaysShown(false);
- return decimalFormat.format(inputDecimal);
- }
-
- /**
- * Formats the download count with a suffix
- *
- * @param downloadCount number of downloads
- * @return a formatted string
- */
- private String formatDownloadCount(long downloadCount) {
- double reducedCount = downloadCount;
- int reductions = 0;
-
- while (reducedCount > PULLS_REDUCER && reductions < MAX_REDUCTIONS) {
- reductions++;
- reducedCount = reducedCount / PULLS_REDUCER;
- }
-
- return formatDecimal(reducedCount, "0.#") + PULLS_SUFFIX.get(reductions);
+ private boolean isTag(ArtifactoryFolderElement child) {
+ return child.isFolder() && !artifactoryConfig.getExcludedFolders().contains(child.getUri());
}
}
diff --git a/src/main/java/io/github/devatherock/artifactory/service/DockerBadgeServiceHelper.java b/src/main/java/io/github/devatherock/artifactory/service/DockerBadgeServiceHelper.java
new file mode 100644
index 0000000..1cd1a3c
--- /dev/null
+++ b/src/main/java/io/github/devatherock/artifactory/service/DockerBadgeServiceHelper.java
@@ -0,0 +1,165 @@
+package io.github.devatherock.artifactory.service;
+
+import java.text.DecimalFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import io.github.devatherock.artifactory.entities.ArtifactoryFolderInfo;
+
+import io.micronaut.core.annotation.Blocking;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+/**
+ * Helper class for {@link DockerBadgeService}
+ *
+ * @author devaprasadh
+ */
+@Blocking
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class DockerBadgeServiceHelper {
+ private static final double PULLS_REDUCER = 1000;
+ private static final int MAX_REDUCTIONS = 3;
+
+ /**
+ * Major version part of a semantic version
+ */
+ private static final String VERSION_PART_MAJOR = "major";
+ /**
+ * Minor version part of a semantic version
+ */
+ private static final String VERSION_PART_MINOR = "minor";
+ /**
+ * Patch version part of a semantic version
+ */
+ private static final String VERSION_PART_PATCH = "patch";
+ /**
+ * Map containing suffixes for download count
+ */
+ private static final Map PULLS_SUFFIX = new HashMap<>();
+ /**
+ * Pattern to match versions like {@code 1}, {@code 1.2} and {@code 1.2.2}
+ */
+ private static final Pattern PTRN_NUMERIC_VERSION = Pattern.compile(
+ "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))*(\\-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$");
+ /**
+ * Pattern to match numbers
+ */
+ private static final Pattern PTRN_NUMBER = Pattern.compile("^[0-9]+$");
+
+ static {
+ PULLS_SUFFIX.put(0, "");
+ PULLS_SUFFIX.put(1, "k");
+ PULLS_SUFFIX.put(2, "M");
+ PULLS_SUFFIX.put(3, "G");
+ }
+
+ /**
+ * Compares two versions
+ *
+ * @param versionOne
+ * @param versionTwo
+ * @param versionPartType
+ * @return {@literal -1} if {@code versionTwo} greater than {@code versionOne},
+ * {@literal 1} otherwise
+ */
+ static int compareVersions(String versionOne, String versionTwo, String versionPartType) {
+ int result = 0;
+
+ int versionPartEndOne = getVersionPartEndIndex(versionOne);
+ String versionPartOneText = versionOne.substring(0,
+ versionPartEndOne != -1 ? versionPartEndOne : versionOne.length());
+ long versionPartOne = readVersionAsNumber(versionPartOneText);
+ int versionPartEndTwo = getVersionPartEndIndex(versionTwo);
+ String versionPartTwoText = versionTwo.substring(0,
+ versionPartEndTwo != -1 ? versionPartEndTwo : versionTwo.length());
+ long versionPartTwo = readVersionAsNumber(versionPartTwoText);
+
+ if (versionPartOne > versionPartTwo) {
+ result = 1;
+ } else if (versionPartOne < versionPartTwo) {
+ result = -1;
+ } else {
+ if ((versionPartOneText.length() + 1) >= versionOne.length()) {
+ if ((versionPartTwoText.length() + 1) < versionTwo.length()) {
+ result = -1;
+ }
+ } else if ((versionPartTwoText.length() + 1) < versionTwo.length()) {
+ if (!VERSION_PART_PATCH.equals(versionPartType)) {
+ result = compareVersions(versionOne.substring(versionPartEndOne + 1),
+ versionTwo.substring(versionPartEndTwo + 1),
+ VERSION_PART_MAJOR.equals(versionPartType) ? VERSION_PART_MINOR : VERSION_PART_PATCH);
+ }
+ } else {
+ result = 1;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the formatted value to be displayed in the version badge
+ *
+ * @param version
+ * @return the version badge value
+ */
+ static String getVersionBadgeValue(ArtifactoryFolderInfo version) {
+ String versionValue = version.getPath().substring(version.getPath().lastIndexOf('/') + 1);
+
+ // Append v prefix if version is numeric or a semantic version
+ return PTRN_NUMERIC_VERSION.matcher(versionValue).matches() ? 'v' + versionValue : versionValue;
+ }
+
+ /**
+ * Formats a decimal number into a string
+ *
+ * @param inputDecimal the decimal number to format
+ * @param format the pattern to which to format to
+ * @return a formatted string
+ */
+ static String formatDecimal(double inputDecimal, String format) {
+ DecimalFormat decimalFormat = new DecimalFormat(format);
+ decimalFormat.setDecimalSeparatorAlwaysShown(false);
+ return decimalFormat.format(inputDecimal);
+ }
+
+ /**
+ * Formats the download count with a suffix
+ *
+ * @param downloadCount number of downloads
+ * @return a formatted string
+ */
+ static String formatDownloadCount(long downloadCount) {
+ double reducedCount = downloadCount;
+ int reductions = 0;
+
+ while (reducedCount > PULLS_REDUCER && reductions < MAX_REDUCTIONS) {
+ reductions++;
+ reducedCount = reducedCount / PULLS_REDUCER;
+ }
+
+ return formatDecimal(reducedCount, "0.#") + PULLS_SUFFIX.get(reductions);
+ }
+
+ /**
+ * Returns the index at which the first version part ends
+ *
+ * @param version
+ * @return the index
+ */
+ private static int getVersionPartEndIndex(String version) {
+ return version.indexOf('.') != -1 ? version.indexOf('.') : version.indexOf('-');
+ }
+
+ /**
+ * Converts version string into a number
+ *
+ * @param version
+ * @return the version as number
+ */
+ private static long readVersionAsNumber(String version) {
+ return PTRN_NUMBER.matcher(version).matches() ? Long.parseLong(version) : 0;
+ }
+}
diff --git a/src/main/java/io/github/devatherock/test/ArtifactoryController.java b/src/main/java/io/github/devatherock/test/ArtifactoryController.java
index 4c8f714..659d2e5 100644
--- a/src/main/java/io/github/devatherock/test/ArtifactoryController.java
+++ b/src/main/java/io/github/devatherock/test/ArtifactoryController.java
@@ -33,6 +33,7 @@ public class ArtifactoryController {
MODIFIED_TIME.put("latest", "2020-10-01T00:00:00.000Z");
MODIFIED_TIME.put("1.1.0", "2020-10-08T00:00:00.000Z");
MODIFIED_TIME.put("1.1.2-rc.1", "2020-10-15T00:00:00.000Z");
+ MODIFIED_TIME.put("_uploads", "2021-03-15T00:00:00.000Z");
}
@Get(value = "/{fileName:.*}", produces = MediaType.APPLICATION_JSON)
@@ -68,6 +69,7 @@ public Object getFolderInfo(@PathVariable String folderName,
.child(ArtifactoryFolderElement.builder().uri("/1.1.0").folder(true).build())
.child(ArtifactoryFolderElement.builder().uri("/1.1.2-rc.1").folder(true).build())
.child(ArtifactoryFolderElement.builder().uri("/latest").folder(true).build())
+ .child(ArtifactoryFolderElement.builder().uri("/_uploads").folder(true).build())
.child(ArtifactoryFolderElement.builder().uri("/dummy").folder(false).build())
.build();
}
diff --git a/src/main/resources/application-mock.yml b/src/main/resources/application-local.yml
similarity index 100%
rename from src/main/resources/application-mock.yml
rename to src/main/resources/application-local.yml
diff --git a/src/test/groovy/io/github/devatherock/artifactory/controllers/DockerControllerSpec.groovy b/src/test/groovy/io/github/devatherock/artifactory/controllers/DockerControllerSpec.groovy
index a97749d..e1c9684 100644
--- a/src/test/groovy/io/github/devatherock/artifactory/controllers/DockerControllerSpec.groovy
+++ b/src/test/groovy/io/github/devatherock/artifactory/controllers/DockerControllerSpec.groovy
@@ -87,6 +87,8 @@ class DockerControllerSpec extends Specification {
WireMock.verify(1,
WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/abcdefgh/manifest.json?stats"))
.withHeader(DockerBadgeService.HDR_API_KEY, equalTo('dummyKey')))
+ WireMock.verify(0,
+ WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/_uploads/manifest.json?stats")))
WireMock.verify(1, WireMock.getRequestedFor(WireMock.urlPathEqualTo("/static/v1")))
badge == TestUtil.getCustomBadgeResponse()
}
@@ -135,6 +137,8 @@ class DockerControllerSpec extends Specification {
WireMock.verify(1,
WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/abcdefgh/manifest.json?stats"))
.withHeader(DockerBadgeService.HDR_API_KEY, equalTo('dummyKey')))
+ WireMock.verify(0,
+ WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/_uploads/manifest.json?stats")))
WireMock.verify(1, WireMock.getRequestedFor(WireMock.urlPathEqualTo("/static/v1")))
badge == 'dummyBadge'
}
@@ -187,6 +191,8 @@ class DockerControllerSpec extends Specification {
WireMock.verify(1,
WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/abcdefgh/manifest.json?stats"))
.withHeader(DockerBadgeService.HDR_API_KEY, equalTo('dummyKey')))
+ WireMock.verify(0,
+ WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/_uploads/manifest.json?stats")))
WireMock.verify(1, WireMock.getRequestedFor(WireMock.urlPathEqualTo("/static/v1")))
badge == 'dummyBadge'
cachedBadge == badge
diff --git a/src/test/groovy/io/github/devatherock/artifactory/controllers/VersionControllerSpec.groovy b/src/test/groovy/io/github/devatherock/artifactory/controllers/VersionControllerSpec.groovy
index b580f3d..f79d3b4 100644
--- a/src/test/groovy/io/github/devatherock/artifactory/controllers/VersionControllerSpec.groovy
+++ b/src/test/groovy/io/github/devatherock/artifactory/controllers/VersionControllerSpec.groovy
@@ -91,6 +91,8 @@ class VersionControllerSpec extends Specification {
WireMock.verify(1,
WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/abcdefgh"))
.withHeader(DockerBadgeService.HDR_API_KEY, equalTo('dummyKey')))
+ WireMock.verify(0,
+ WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/_uploads")))
WireMock.verify(1, WireMock.getRequestedFor(WireMock.urlPathEqualTo("/static/v1")))
badge == 'dummyBadge'
}
@@ -143,6 +145,8 @@ class VersionControllerSpec extends Specification {
WireMock.verify(1,
WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/abcdefgh"))
.withHeader(DockerBadgeService.HDR_API_KEY, equalTo('dummyKey')))
+ WireMock.verify(0,
+ WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/_uploads")))
WireMock.verify(1, WireMock.getRequestedFor(WireMock.urlPathEqualTo("/static/v1")))
badge == 'dummyBadge'
}
@@ -199,6 +203,8 @@ class VersionControllerSpec extends Specification {
WireMock.verify(1,
WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/abcdefgh"))
.withHeader(DockerBadgeService.HDR_API_KEY, equalTo('dummyKey')))
+ WireMock.verify(0,
+ WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/_uploads")))
WireMock.verify(1, WireMock.getRequestedFor(WireMock.urlPathEqualTo("/static/v1")))
badge == 'dummyBadge'
cachedBadge == badge
@@ -237,6 +243,8 @@ class VersionControllerSpec extends Specification {
WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/latest")))
WireMock.verify(0,
WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/abcdefgh")))
+ WireMock.verify(0,
+ WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/_uploads")))
WireMock.verify(1, WireMock.getRequestedFor(WireMock.urlPathEqualTo("/static/v1")))
badge == 'dummyBadge'
}
diff --git a/src/test/groovy/io/github/devatherock/artifactory/service/DockerBadgeServiceHelperSpec.groovy b/src/test/groovy/io/github/devatherock/artifactory/service/DockerBadgeServiceHelperSpec.groovy
new file mode 100644
index 0000000..7097307
--- /dev/null
+++ b/src/test/groovy/io/github/devatherock/artifactory/service/DockerBadgeServiceHelperSpec.groovy
@@ -0,0 +1,52 @@
+package io.github.devatherock.artifactory.service
+
+import io.github.devatherock.artifactory.entities.ArtifactoryFolderInfo
+
+import spock.lang.Specification
+
+/**
+ * Test class for {@link DockerBadgeServiceHelper}
+ */
+class DockerBadgeServiceHelperSpec extends Specification {
+
+ void 'test get version badge value'() {
+ expect:
+ DockerBadgeServiceHelper.getVersionBadgeValue(new ArtifactoryFolderInfo(path: path)) == outputVersion
+
+ where:
+ path | outputVersion
+ 'docker/devatherock/simple-slack/1.1.0' | 'v1.1.0'
+ 'docker/devatherock/simple-slack/latest' | 'latest'
+ }
+
+ void 'test format download count'() {
+ expect:
+ DockerBadgeServiceHelper.formatDownloadCount(downloadCount) == formattedCount
+
+ where:
+ downloadCount | formattedCount
+ 450 | '450'
+ 1249 | '1.2k'
+ 1251 | '1.3k'
+ 1_100_000 | '1.1M'
+ 1_100_000_000 | '1.1G'
+ 1_100_000_000_000 | '1100G'
+ }
+
+ void 'test compare versions'() {
+ expect:
+ DockerBadgeServiceHelper.compareVersions(versionOne, versionTwo, 'major') == expectedResult
+
+ where:
+ versionOne | versionTwo | expectedResult
+ '2' | '1.1' | 1
+ '1' | '1.1' | -1
+ '1.1-alpha' | '1.1-beta' | 0
+ '1.1.1-alpha' | '1.1.1-beta' | 0
+ '2.5-alpine' | '2.5' | 1
+ '2.5' | '2.5-alpine' | -1
+ '1.1.1' | '1.1.2' | -1
+ '1.1.2' | '1.1.1' | 1
+ '1.1.2' | '1.1.2' | 0
+ }
+}
diff --git a/src/test/groovy/io/github/devatherock/artifactory/service/DockerBadgeServiceSpec.groovy b/src/test/groovy/io/github/devatherock/artifactory/service/DockerBadgeServiceSpec.groovy
index b32b869..0b46063 100644
--- a/src/test/groovy/io/github/devatherock/artifactory/service/DockerBadgeServiceSpec.groovy
+++ b/src/test/groovy/io/github/devatherock/artifactory/service/DockerBadgeServiceSpec.groovy
@@ -308,6 +308,8 @@ class DockerBadgeServiceSpec extends Specification {
WireMock.verify(1,
WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/abcdefgh"))
.withHeader(DockerBadgeService.HDR_API_KEY, equalTo('dummyKey')))
+ WireMock.verify(0,
+ WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/_uploads")))
1 * badgeGenerator.generateBadge('version', 'v1.1.0') >> 'dummyBadge'
badge == 'dummyBadge'
}
@@ -328,37 +330,13 @@ class DockerBadgeServiceSpec extends Specification {
WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}"))
.withHeader(DockerBadgeService.HDR_API_KEY, equalTo('dummyKey')))
WireMock.verify(0,
- WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/1.1.0")))
+ WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/1.1.0-alpha")))
WireMock.verify(0,
- WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/1.1.2")))
+ WireMock.getRequestedFor(urlEqualTo("/artifactory/api/storage/${packageName}/1.1.0-beta")))
1 * badgeGenerator.generateBadge('version', 'v1.1.0-alpha') >> 'dummyBadge'
badge == 'dummyBadge'
}
- void 'test get version badge value'() {
- expect:
- dockerBadgeService.getVersionBadgeValue(new ArtifactoryFolderInfo(path: path)) == outputVersion
-
- where:
- path | outputVersion
- 'docker/devatherock/simple-slack/1.1.0' | 'v1.1.0'
- 'docker/devatherock/simple-slack/latest' | 'latest'
- }
-
- void 'test format download count'() {
- expect:
- dockerBadgeService.formatDownloadCount(downloadCount) == formattedCount
-
- where:
- downloadCount | formattedCount
- 450 | '450'
- 1249 | '1.2k'
- 1251 | '1.3k'
- 1_100_000 | '1.1M'
- 1_100_000_000 | '1.1G'
- 1_100_000_000_000 | '1100G'
- }
-
void 'test generate not found badge'() {
when:
String badge = dockerBadgeService.generateNotFoundBadge('layers')
@@ -367,21 +345,4 @@ class DockerBadgeServiceSpec extends Specification {
1 * badgeGenerator.generateBadge('layers', 'Not Found') >> 'dummyBadge'
badge == 'dummyBadge'
}
-
- void 'test compare versions'() {
- expect:
- dockerBadgeService.compareVersions(versionOne, versionTwo, 'major') == expectedResult
-
- where:
- versionOne | versionTwo | expectedResult
- '2' | '1.1' | 1
- '1' | '1.1' | -1
- '1.1-alpha' | '1.1-beta' | 0
- '1.1.1-alpha' | '1.1.1-beta' | 0
- '2.5-alpine' | '2.5' | 1
- '2.5' | '2.5-alpine' | -1
- '1.1.1' | '1.1.2' | -1
- '1.1.2' | '1.1.1' | 1
- '1.1.2' | '1.1.2' | 0
- }
}
diff --git a/src/test/groovy/io/github/devatherock/test/TestUtil.groovy b/src/test/groovy/io/github/devatherock/test/TestUtil.groovy
index 3647f85..02791d0 100644
--- a/src/test/groovy/io/github/devatherock/test/TestUtil.groovy
+++ b/src/test/groovy/io/github/devatherock/test/TestUtil.groovy
@@ -23,6 +23,10 @@ class TestUtil {
"uri": "/1.1.2",
"folder": true
},
+ {
+ "uri": "/_uploads",
+ "folder": true
+ },
{
"uri": "/latest",
"folder": true