From b1d63aee3583495b3df77369dececdfbd6d27e5e Mon Sep 17 00:00:00 2001 From: samfreund Date: Fri, 28 Nov 2025 21:22:43 -0600 Subject: [PATCH] use updated image metadata --- .../common/hardware/OsImageData.java | 97 +++++++++++++++++++ .../common/hardware/OsImageVersion.java | 55 ----------- .../src/main/java/org/photonvision/Main.java | 10 +- 3 files changed, 104 insertions(+), 58 deletions(-) create mode 100644 photon-core/src/main/java/org/photonvision/common/hardware/OsImageData.java delete mode 100644 photon-core/src/main/java/org/photonvision/common/hardware/OsImageVersion.java diff --git a/photon-core/src/main/java/org/photonvision/common/hardware/OsImageData.java b/photon-core/src/main/java/org/photonvision/common/hardware/OsImageData.java new file mode 100644 index 0000000000..5dbb5af85a --- /dev/null +++ b/photon-core/src/main/java/org/photonvision/common/hardware/OsImageData.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) Photon Vision. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.photonvision.common.hardware; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; +import org.photonvision.common.logging.LogGroup; +import org.photonvision.common.logging.Logger; + +/** + * Our blessed images inject the current version via the build process in + * https://github.com/PhotonVision/photon-image-modifier + * + *

This class provides a convenient abstraction around this + */ +public class OsImageData { + private static final Logger logger = new Logger(OsImageData.class, LogGroup.General); + + private static Path imageVersionFile = Path.of("/opt/photonvision/image-version"); + private static Path imageMetadataFile = Path.of("/opt/photonvision/image-version.json"); + + /** The OS image version string, if available. This is legacy, use {@link ImageMetadata}. */ + public static final Optional IMAGE_VERSION = getImageVersion(); + + private static Optional getImageVersion() { + if (!imageVersionFile.toFile().exists()) { + logger.warn("Photon cannot locate base OS image version at " + imageVersionFile.toString()); + return Optional.empty(); + } + + try { + return Optional.of(Files.readString(imageVersionFile).strip()); + } catch (IOException e) { + logger.error("Couldn't read image-version file", e); + } + + return Optional.empty(); + } + + public static final Optional IMAGE_METADATA = getImageMetadata(); + + public static record ImageMetadata( + String buildDate, String commitSha, String commitTag, String imageName, String imageSource) {} + + private static Optional getImageMetadata() { + if (!imageMetadataFile.toFile().exists()) { + logger.warn("Photon cannot locate OS image metadata at " + imageMetadataFile.toString()); + return Optional.empty(); + } + + try { + String content = Files.readString(imageMetadataFile).strip(); + + ObjectMapper mapper = + new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + + ImageMetadata md = mapper.readValue(content, ImageMetadata.class); + + if (md.buildDate() == null + && md.commitSha() == null + && md.commitTag() == null + && md.imageName() == null + && md.imageSource() == null) { + logger.warn( + "OS image metadata JSON did not contain recognized fields; preserving legacy behavior"); + return Optional.empty(); + } + + return Optional.of(md); + } catch (IOException e) { + logger.error("Couldn't read image metadata file", e); + } catch (Exception e) { + logger.error("Failed to parse image metadata", e); + } + + return Optional.empty(); + } +} diff --git a/photon-core/src/main/java/org/photonvision/common/hardware/OsImageVersion.java b/photon-core/src/main/java/org/photonvision/common/hardware/OsImageVersion.java deleted file mode 100644 index 7b00abf20a..0000000000 --- a/photon-core/src/main/java/org/photonvision/common/hardware/OsImageVersion.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) Photon Vision. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.photonvision.common.hardware; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Optional; -import org.photonvision.common.logging.LogGroup; -import org.photonvision.common.logging.Logger; - -/** - * Our blessed images inject the current version via this build workflow: - * https://github.com/PhotonVision/photon-image-modifier/blob/2e5ddb6b599df0be921c12c8dbe7b939ecd7f615/.github/workflows/main.yml#L67 - * - *

This class provides a convenient abstraction around this - */ -public class OsImageVersion { - private static final Logger logger = new Logger(OsImageVersion.class, LogGroup.General); - - private static Path imageVersionFile = Path.of("/opt/photonvision/image-version"); - - public static final Optional IMAGE_VERSION = getImageVersion(); - - private static Optional getImageVersion() { - if (!imageVersionFile.toFile().exists()) { - logger.warn( - "Photon cannot locate base OS image version metadata at " + imageVersionFile.toString()); - return Optional.empty(); - } - - try { - return Optional.of(Files.readString(imageVersionFile).strip()); - } catch (IOException e) { - logger.error("Couldn't read image-version file", e); - } - - return Optional.empty(); - } -} diff --git a/photon-server/src/main/java/org/photonvision/Main.java b/photon-server/src/main/java/org/photonvision/Main.java index 130bd25ba8..4e03758e29 100644 --- a/photon-server/src/main/java/org/photonvision/Main.java +++ b/photon-server/src/main/java/org/photonvision/Main.java @@ -28,7 +28,7 @@ import org.photonvision.common.configuration.NeuralNetworkModelManager; import org.photonvision.common.dataflow.networktables.NetworkTablesManager; import org.photonvision.common.hardware.HardwareManager; -import org.photonvision.common.hardware.OsImageVersion; +import org.photonvision.common.hardware.OsImageData; import org.photonvision.common.hardware.PiVersion; import org.photonvision.common.hardware.Platform; import org.photonvision.common.logging.KernelLogLogger; @@ -173,8 +173,12 @@ public static void main(String[] args) { + Platform.getPlatformName() + (Platform.isRaspberryPi() ? (" (Pi " + PiVersion.getPiVersion() + ")") : "")); - if (OsImageVersion.IMAGE_VERSION.isPresent()) { - logger.info("PhotonVision image version: " + OsImageVersion.IMAGE_VERSION.get()); + if (OsImageData.IMAGE_METADATA.isPresent()) { + logger.info("PhotonVision image data: " + OsImageData.IMAGE_METADATA.get()); + } else if (OsImageData.IMAGE_VERSION.isPresent()) { + logger.info("PhotonVision image version: " + OsImageData.IMAGE_VERSION.get()); + } else { + logger.info("PhotonVision image version: unknown"); } try {