diff --git a/api/src/main/java/io/kafbat/ui/service/ApplicationInfoService.java b/api/src/main/java/io/kafbat/ui/service/ApplicationInfoService.java index 7ee28b62d..dd5d9c4f9 100644 --- a/api/src/main/java/io/kafbat/ui/service/ApplicationInfoService.java +++ b/api/src/main/java/io/kafbat/ui/service/ApplicationInfoService.java @@ -3,6 +3,7 @@ import static io.kafbat.ui.api.model.AuthType.DISABLED; import static io.kafbat.ui.api.model.AuthType.OAUTH2; import static io.kafbat.ui.model.ApplicationInfoDTO.EnabledFeaturesEnum; +import static io.kafbat.ui.util.GithubReleaseInfo.GITHUB_RELEASE_INFO_ENABLED; import static io.kafbat.ui.util.GithubReleaseInfo.GITHUB_RELEASE_INFO_TIMEOUT; import com.google.common.annotations.VisibleForTesting; @@ -15,12 +16,14 @@ import io.kafbat.ui.model.OAuthProviderDTO; import io.kafbat.ui.util.DynamicConfigOperations; import io.kafbat.ui.util.GithubReleaseInfo; +import jakarta.annotation.Nullable; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Properties; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.info.BuildProperties; @@ -33,7 +36,9 @@ import org.springframework.stereotype.Service; @Service +@Slf4j public class ApplicationInfoService { + @Nullable private final GithubReleaseInfo githubReleaseInfo; private final ApplicationContext applicationContext; private final DynamicConfigOperations dynamicConfigOperations; @@ -44,23 +49,34 @@ public ApplicationInfoService(DynamicConfigOperations dynamicConfigOperations, ApplicationContext applicationContext, @Autowired(required = false) BuildProperties buildProperties, @Autowired(required = false) GitProperties gitProperties, + @Value("${" + GITHUB_RELEASE_INFO_ENABLED + ":true}") boolean githubInfoEnabled, @Value("${" + GITHUB_RELEASE_INFO_TIMEOUT + ":10}") int githubApiMaxWaitTime) { this.applicationContext = applicationContext; this.dynamicConfigOperations = dynamicConfigOperations; this.buildProperties = Optional.ofNullable(buildProperties).orElse(new BuildProperties(new Properties())); this.gitProperties = Optional.ofNullable(gitProperties).orElse(new GitProperties(new Properties())); - githubReleaseInfo = new GithubReleaseInfo(githubApiMaxWaitTime); + if (githubInfoEnabled) { + this.githubReleaseInfo = new GithubReleaseInfo(githubApiMaxWaitTime); + } else { + this.githubReleaseInfo = null; + log.warn("Check for latest release is disabled." + + " Note that old versions are not supported, please make sure that your system is up to date."); + } } public ApplicationInfoDTO getApplicationInfo() { - var releaseInfo = githubReleaseInfo.get(); + var releaseInfo = githubReleaseInfo != null ? githubReleaseInfo.get() : null; return new ApplicationInfoDTO() .build(getBuildInfo(releaseInfo)) .enabledFeatures(getEnabledFeatures()) .latestRelease(convert(releaseInfo)); } + @Nullable private ApplicationInfoLatestReleaseDTO convert(GithubReleaseInfo.GithubReleaseDto releaseInfo) { + if (releaseInfo == null) { + return null; + } return new ApplicationInfoLatestReleaseDTO() .htmlUrl(releaseInfo.html_url()) .publishedAt(releaseInfo.published_at()) @@ -68,12 +84,17 @@ private ApplicationInfoLatestReleaseDTO convert(GithubReleaseInfo.GithubReleaseD } private ApplicationInfoBuildDTO getBuildInfo(GithubReleaseInfo.GithubReleaseDto release) { - return new ApplicationInfoBuildDTO() - .isLatestRelease(release.tag_name() != null && release.tag_name().equals(buildProperties.getVersion())) + var buildInfo = new ApplicationInfoBuildDTO() .commitId(gitProperties.getShortCommitId()) .version(buildProperties.getVersion()) .buildTime(buildProperties.getTime() != null ? DateTimeFormatter.ISO_INSTANT.format(buildProperties.getTime()) : null); + if (release != null) { + buildInfo = buildInfo.isLatestRelease( + release.tag_name() != null && release.tag_name().equals(buildProperties.getVersion()) + ); + } + return buildInfo; } private List getEnabledFeatures() { @@ -119,10 +140,13 @@ private List getOAuthProviders() { // updating on startup and every hour @Scheduled(fixedRateString = "${github-release-info-update-rate:3600000}") public void updateGithubReleaseInfo() { - githubReleaseInfo.refresh().subscribe(); + if (githubReleaseInfo != null) { + githubReleaseInfo.refresh().subscribe(); + } } @VisibleForTesting + @Nullable GithubReleaseInfo githubReleaseInfo() { return githubReleaseInfo; } diff --git a/api/src/main/java/io/kafbat/ui/util/GithubReleaseInfo.java b/api/src/main/java/io/kafbat/ui/util/GithubReleaseInfo.java index ba767a65a..8e87796ad 100644 --- a/api/src/main/java/io/kafbat/ui/util/GithubReleaseInfo.java +++ b/api/src/main/java/io/kafbat/ui/util/GithubReleaseInfo.java @@ -8,6 +8,7 @@ @Slf4j public class GithubReleaseInfo { + public static final String GITHUB_RELEASE_INFO_ENABLED = "github.release.info.enabled"; public static final String GITHUB_RELEASE_INFO_TIMEOUT = "github.release.info.timeout"; private static final String GITHUB_LATEST_RELEASE_RETRIEVAL_URL = diff --git a/api/src/test/java/io/kafbat/ui/service/ApplicationInfoServiceTest.java b/api/src/test/java/io/kafbat/ui/service/ApplicationInfoServiceTest.java index a4cae637b..f81429d59 100644 --- a/api/src/test/java/io/kafbat/ui/service/ApplicationInfoServiceTest.java +++ b/api/src/test/java/io/kafbat/ui/service/ApplicationInfoServiceTest.java @@ -1,8 +1,11 @@ package io.kafbat.ui.service; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import io.kafbat.ui.AbstractIntegrationTest; +import io.kafbat.ui.util.DynamicConfigOperations; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -10,8 +13,31 @@ class ApplicationInfoServiceTest extends AbstractIntegrationTest { @Autowired private ApplicationInfoService service; + @Autowired + private DynamicConfigOperations dynamicConfigOperations; + @Test void testCustomGithubReleaseInfoTimeout() { assertEquals(100, service.githubReleaseInfo().getGithubApiMaxWaitTime()); } + + @Test + void testDisabledReleaseInfo() { + var service2 = new ApplicationInfoService( + dynamicConfigOperations, + null, + null, + null, + false, + 101 + ); + + assertNull(service2.githubReleaseInfo(), "unexpected GitHub release info when disabled"); + var appInfo = service2.getApplicationInfo(); + assertNotNull(appInfo, "application info must not be NULL"); + assertNull(appInfo.getLatestRelease(), "latest release should be NULL when disabled"); + assertNotNull(appInfo.getBuild(), "build info must not be NULL"); + assertNotNull(appInfo.getEnabledFeatures(), "enabled features must not be NULL"); + } + } diff --git a/frontend/src/components/Version/Version.tsx b/frontend/src/components/Version/Version.tsx index 775fbfa5d..dd46131b4 100644 --- a/frontend/src/components/Version/Version.tsx +++ b/frontend/src/components/Version/Version.tsx @@ -3,6 +3,7 @@ import WarningIcon from 'components/common/Icons/WarningIcon'; import { gitCommitPath } from 'lib/paths'; import { useLatestVersion } from 'lib/hooks/api/latestVersion'; import { formatTimestamp } from 'lib/dateTimeHelpers'; +import { useTheme } from 'styled-components'; import * as S from './Version.styled'; @@ -17,9 +18,16 @@ const Version: React.FC = () => { ? versionTag : formatTimestamp(buildTime); + const theme = useTheme(); + return ( - {!isLatestRelease && ( + {isLatestRelease === null && ( + + + + )} + {isLatestRelease === false && ( { +const WarningIcon: React.FC<{ color?: string }> = ({ color }) => { + const theme = useTheme(); return ( { fillRule="evenodd" clipRule="evenodd" d="M8.09265 1.06679C7.60703 0.250524 6.39297 0.250524 5.90735 1.06679L0.170916 10.7089C-0.314707 11.5252 0.292322 12.5455 1.26357 12.5455H12.7364C13.7077 12.5455 14.3147 11.5252 13.8291 10.7089L8.09265 1.06679ZM6 5.00006C6 4.44778 6.44772 4.00006 7 4.00006C7.55228 4.00006 8 4.44778 8 5.00006V7.00006C8 7.55235 7.55228 8.00006 7 8.00006C6.44772 8.00006 6 7.55235 6 7.00006V5.00006ZM6 10.0001C6 9.44778 6.44772 9.00006 7 9.00006C7.55228 9.00006 8 9.44778 8 10.0001C8 10.5523 7.55228 11.0001 7 11.0001C6.44772 11.0001 6 10.5523 6 10.0001Z" - fill="#F2C94C" + fill={color || theme.icons.warningIcon} />