feat: version banner UI + GET /api/v1/version backend endpoint
This commit is contained in:
+81
@@ -0,0 +1,81 @@
|
||||
package cloud.nstart.terravault.ordinis.restapi.web;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.info.BuildProperties;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* {@code GET /api/v1/version} — экспонирует server build identity для UI
|
||||
* update-detection banner.
|
||||
*
|
||||
* <p>Frontend (admin-ui) bundle'ит свой commit SHA в build-time через Vite
|
||||
* {@code define.__APP_COMMIT__}. Periodic poll этого endpoint'а сравнивает
|
||||
* server commit vs client commit. Mismatch → "Доступна новая версия" banner с
|
||||
* CTA {@code Обновить} (window.location.reload).
|
||||
*
|
||||
* <p>Source данных:
|
||||
* <ul>
|
||||
* <li>{@code BuildProperties} bean создаётся Spring Boot когда есть
|
||||
* {@code META-INF/build-info.properties} (генерируется
|
||||
* spring-boot-maven-plugin {@code build-info} goal в ordinis-app pom).</li>
|
||||
* <li>Дополнительные {@code commit}, {@code branch}, {@code tag}
|
||||
* resolved из CI env vars (см. additionalProperties в plugin config).</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Если build-info.properties отсутствует (e.g., запуск в IDE без mvn package)
|
||||
* — возвращает sensible defaults чтобы UI не падал.
|
||||
*
|
||||
* <p>Public endpoint — auth НЕ required (нужен на login screen чтобы клиент
|
||||
* сразу знал stale ли его bundle).
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/version")
|
||||
public class VersionController {
|
||||
|
||||
private final Optional<BuildProperties> buildProps;
|
||||
|
||||
// BuildProperties может отсутствовать в dev — оптимально через Optional.
|
||||
public VersionController(@Autowired(required = false) BuildProperties buildProps) {
|
||||
this.buildProps = Optional.ofNullable(buildProps);
|
||||
}
|
||||
|
||||
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public VersionInfo current() {
|
||||
return buildProps.map(b -> new VersionInfo(
|
||||
b.getVersion(),
|
||||
Optional.ofNullable(b.get("commit")).orElse("unknown"),
|
||||
Optional.ofNullable(b.get("branch")).orElse(""),
|
||||
Optional.ofNullable(b.get("tag")).orElse(""),
|
||||
b.getTime() != null ? b.getTime().toString() : ""
|
||||
)).orElseGet(() -> new VersionInfo(
|
||||
"0.0.0-dev",
|
||||
"unknown",
|
||||
"",
|
||||
"",
|
||||
Instant.now().toString()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stable JSON shape для UI client.
|
||||
*
|
||||
* @param version Maven {@code project.version} (e.g. "0.1.0-SNAPSHOT" или "1.1.0")
|
||||
* @param commit short git SHA (e.g. "07c5ca0") — primary update detection key
|
||||
* @param branch git branch (e.g. "main"), empty в tag builds
|
||||
* @param tag git tag if applicable (e.g. "v1.1.0"), empty в branch builds
|
||||
* @param builtAt ISO-8601 instant
|
||||
*/
|
||||
public record VersionInfo(
|
||||
String version,
|
||||
String commit,
|
||||
String branch,
|
||||
String tag,
|
||||
String builtAt
|
||||
) {}
|
||||
}
|
||||
Reference in New Issue
Block a user