Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.nvidia.boot.core.cors.ServletCoreCorsConfiguration;
import com.nvidia.boot.core.cors.ReactiveCoreCorsConfiguration;
import com.nvidia.boot.core.health.HealthConfiguration;
import com.nvidia.boot.core.info.InfoConfiguration;
import com.nvidia.boot.core.openapi.OpenApiConfiguration;
import com.nvidia.boot.core.openapi.ServletOpenApiCorsConfiguration;
import com.nvidia.boot.core.openapi.ReactiveOpenApiCorsConfiguration;
Expand All @@ -29,6 +30,7 @@
@AutoConfiguration
@Import({
HealthConfiguration.class,
InfoConfiguration.class,
OpenApiConfiguration.class,
ReactiveCoreCorsConfiguration.class,
ReactiveOpenApiCorsConfiguration.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ private void loadAppVersionFromGitProperties(ConfigurableEnvironment environment
versionProps.put("app.git.commit", commitId);
}

var commitIdFull = gitProperties.getProperty("git.commit.id.full");
if (StringUtils.isNotBlank(commitIdFull)) {
versionProps.put("app.git.commit.full", commitIdFull);
}

var branch = gitProperties.getProperty("git.branch");
if (StringUtils.isNotBlank(branch)) {
versionProps.put("app.git.branch", branch);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.nvidia.boot.core.info;

import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

/** Auto-configuration for the shared {@code GET /info} endpoint and controller. */
@Configuration
@ConditionalOnWebApplication
public class InfoConfiguration {

@Bean
public InfoResponseService infoResponseService(Environment environment) {
return new InfoResponseService(environment);
}

@Bean
public InfoController infoController(InfoResponseService infoResponseService) {
return new InfoController(infoResponseService);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.nvidia.boot.core.info;

import com.nvidia.boot.core.info.InfoResponseService.InfoResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* Shared build-info controller for {@code GET /info}. Returns a flat {service, version, commit}
* body, matching the equivalent Go services' contract, so build identification is consistent
* across NVCF control plane services.
*/
@RestController
@RequiredArgsConstructor
public class InfoController {

private final InfoResponseService infoResponseService;

@GetMapping("/info")
public ResponseEntity<InfoResponse> getInfo() {
return ResponseEntity.ok(infoResponseService.getInfo());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.nvidia.boot.core.info;

import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.env.Environment;

@RequiredArgsConstructor
public class InfoResponseService {

private static final String UNKNOWN = "unknown";

private final Environment environment;

public InfoResponse getInfo() {
return new InfoResponse(
resolve("spring.application.name"),
resolve("spring.application.version"),
resolve("app.git.commit.full"));
}

private String resolve(String key) {
String value = environment.getProperty(key);
return StringUtils.isBlank(value) ? UNKNOWN : value;
}

public record InfoResponse(String service, String version, String commit) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ void usesClosestTagNameAsVersionWhenPresent() {
git.closest.tag.name=v2.5.0
git.build.version=2.5.0-SNAPSHOT
git.commit.id.abbrev=abc1234
git.commit.id.full=abc1234def5678901234567890abcdef12345678
""");

assertThat(env.getProperty("spring.application.version")).isEqualTo("v2.5.0");
assertThat(env.getProperty("app.git.tag")).isEqualTo("v2.5.0");
assertThat(env.getProperty("app.git.commit")).isEqualTo("abc1234");
assertThat(env.getProperty("app.git.commit.full")).isEqualTo("abc1234def5678901234567890abcdef12345678");
assertThat(env.getProperty("app.git.branch")).isNull();
}

Expand Down Expand Up @@ -96,6 +98,7 @@ void fallsBackToUnknownWhenAllVersionFieldsAbsent() {
assertThat(env.getProperty("spring.application.version")).isEqualTo("unknown");
assertThat(env.getProperty("app.git.tag")).isNull();
assertThat(env.getProperty("app.git.commit")).isNull();
assertThat(env.getProperty("app.git.commit.full")).isNull();
assertThat(env.getProperty("app.git.branch")).isEqualTo("main");
}

Expand All @@ -105,10 +108,12 @@ void populatesAllGitMetadataProperties() {
git.closest.tag.name=v2.5.0
git.build.version=2.5.0-SNAPSHOT
git.commit.id.abbrev=abc1234
git.commit.id.full=abc1234def5678901234567890abcdef12345678
git.branch=main
""");

assertThat(env.getProperty("app.git.commit")).isEqualTo("abc1234");
assertThat(env.getProperty("app.git.commit.full")).isEqualTo("abc1234def5678901234567890abcdef12345678");
assertThat(env.getProperty("app.git.branch")).isEqualTo("main");
assertThat(env.getProperty("app.git.tag")).isEqualTo("v2.5.0");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.nvidia.boot.core.info;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.nvidia.boot.core.info.InfoResponseService.InfoResponse;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class InfoControllerTest {

private InfoResponseService infoResponseService;
private InfoController controller;

@BeforeEach
void setUp() {
infoResponseService = mock(InfoResponseService.class);
controller = new InfoController(infoResponseService);
}

@Test
void getInfoReturnsOkWithResponseBody() {
var expected = new InfoResponse("nvcf-ess", "v1.2.3", "77c5d932abcdef1234567890abcdef1234567890");
when(infoResponseService.getInfo()).thenReturn(expected);

var response = controller.getInfo();

assertThat(response.getStatusCode().is2xxSuccessful()).isTrue();
assertThat(response.getBody()).isEqualTo(expected);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.nvidia.boot.core.info;

import static org.assertj.core.api.Assertions.assertThat;

import com.nvidia.boot.core.info.InfoResponseService.InfoResponse;
import org.junit.jupiter.api.Test;
import org.springframework.mock.env.MockEnvironment;

class InfoResponseServiceTest {

@Test
void buildsResponseFromEnvironmentProperties() {
var environment = new MockEnvironment()
.withProperty("spring.application.name", "nvcf-ess")
.withProperty("spring.application.version", "v1.2.3")
.withProperty("app.git.commit.full", "77c5d932abcdef1234567890abcdef1234567890");

var service = new InfoResponseService(environment);

assertThat(service.getInfo())
.isEqualTo(new InfoResponse("nvcf-ess", "v1.2.3", "77c5d932abcdef1234567890abcdef1234567890"));
}

@Test
void fallsBackToUnknownWhenPropertiesAbsent() {
var service = new InfoResponseService(new MockEnvironment());

assertThat(service.getInfo()).isEqualTo(new InfoResponse("unknown", "unknown", "unknown"));
}

@Test
void fallsBackToUnknownWhenPropertiesBlank() {
var environment = new MockEnvironment()
.withProperty("spring.application.name", " ")
.withProperty("spring.application.version", "")
.withProperty("app.git.commit.full", "");

var service = new InfoResponseService(environment);

assertThat(service.getInfo()).isEqualTo(new InfoResponse("unknown", "unknown", "unknown"));
}
}
Loading