Integrate smoketests into image build (#2248)

Runs the smoketest on each image after we build it in CI. This helps
ensure that we check every image that we build has the requisite JNI
libraries, and that they can be loaded. This is needed cause we've been
breaking that, and our current smoketests don't actually test all our
libraries since some are gated behind platform checks.
This commit is contained in:
Sam Freund
2025-12-17 10:16:21 -06:00
committed by GitHub
parent 90acd19361
commit 50f2285937
2 changed files with 64 additions and 69 deletions

View File

@@ -409,44 +409,9 @@ jobs:
- run: ls *.jar | %{ Write-Host "Running $($_.Name)"; Start-Process "java" -ArgumentList "-jar `"$($_.FullName)`" --smoketest" -NoNewWindow -Wait; break }
if: ${{ (matrix.os) == 'windows-latest' }}
run-smoketest-chroot:
needs: [build-package]
strategy:
fail-fast: false
matrix:
include:
- image_suffix: RaspberryPi
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_raspi.img.xz
- image_suffix: rubikpi3
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_rubikpi3.tar.xz
root_location: 'offset=569376768'
- image_suffix: orangepi5
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5.img.xz
runs-on: ubuntu-24.04-arm
name: smoketest-${{ matrix.image_suffix }}
steps:
- uses: actions/download-artifact@v4
with:
name: jar-LinuxArm64
- uses: photonvision/photon-image-runner@HEAD
name: Run photon smoketest
id: generate_image
with:
image_url: ${{ matrix.image_url }}
root_location: ${{ matrix.root_location || 'partition=2' }}
# our image better have java installed already
commands: |
java -jar *.jar --smoketest
build-image:
needs: [build-package]
if: ${{ github.event_name != 'pull_request' }}
strategy:
fail-fast: false
matrix:
@@ -454,66 +419,79 @@ jobs:
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: RaspberryPi
plat_override: LINUX_RASPBIAN64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_raspi.img.xz
minimum_free_mb: 100
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: limelight2
plat_override: LINUX_RASPBIAN64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight.img.xz
minimum_free_mb: 100
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: limelight3
plat_override: LINUX_RASPBIAN64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight3.img.xz
minimum_free_mb: 100
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: limelight3G
plat_override: LINUX_RASPBIAN64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight3g.img.xz
minimum_free_mb: 100
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: limelight4
plat_override: LINUX_RASPBIAN64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight4.img.xz
minimum_free_mb: 100
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: luma_p1
plat_override: LINUX_RASPBIAN64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_luma_p1.img.xz
minimum_free_mb: 100
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: orangepi5
plat_override: LINUX_RK3588_64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5.img.xz
minimum_free_mb: 1024
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: orangepi5b
plat_override: LINUX_RK3588_64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5b.img.xz
minimum_free_mb: 1024
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: orangepi5plus
plat_override: LINUX_RK3588_64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5plus.img.xz
minimum_free_mb: 1024
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: orangepi5pro
plat_override: LINUX_RK3588_64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5pro.img.xz
minimum_free_mb: 1024
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: orangepi5max
plat_override: LINUX_RK3588_64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5max.img.xz
minimum_free_mb: 1024
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: rock5c
plat_override: LINUX_RK3588_64
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_rock5c.img.xz
minimum_free_mb: 1024
- os: ubuntu-24.04-arm
artifact-name: LinuxArm64
image_suffix: rubikpi3
plat_override: LINUX_QCS6490
image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_rubikpi3.tar.xz
minimum_free_mb: 1024
root_location: 'offset=569376768'
@@ -541,6 +519,7 @@ jobs:
commands: |
chmod +x scripts/armrunner.sh
./scripts/armrunner.sh
java -jar *.jar --smoketest --platform=${{ matrix.plat_override }}
- name: Compress image
# Compress the standard images
@@ -570,8 +549,16 @@ jobs:
name: image-${{ matrix.image_suffix }}
path: photonvision*.xz
matrix-checker:
runs-on: ubuntu-latest
needs: [build-image]
if: always()
steps:
- run: ${{!contains(needs.*.result, 'failure')}}
release:
needs: [build-photonlib-vendorjson, build-package, build-image, combine]
if: github.ref == ('refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && github.repository == 'PhotonVision/photonvision'
runs-on: ubuntu-22.04
steps:
# Download all fat JARs

View File

@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.commons.cli.*;
import org.photonvision.common.LoadJNI;
import org.photonvision.common.LoadJNI.JNITypes;
import org.photonvision.common.configuration.CameraConfiguration;
import org.photonvision.common.configuration.ConfigManager;
import org.photonvision.common.configuration.NeuralNetworkModelManager;
@@ -53,7 +54,6 @@ public class Main {
public static final int DEFAULT_WEBPORT = 5800;
private static final Logger logger = new Logger(Main.class, LogGroup.General);
private static final boolean isRelease = PhotonVersion.isRelease;
private static boolean isTestMode = false;
private static boolean isSmoketest = false;
@@ -70,7 +70,7 @@ public class Main {
false,
"Run in test mode with 2019 and 2020 WPI field images in place of cameras");
options.addOption("p", "path", true, "Point test mode to a specific folder");
options.addOption("f", "folder", true, "Point test mode to a specific folder");
options.addOption("n", "disable-networking", false, "Disables control device network settings");
options.addOption(
"c",
@@ -82,6 +82,7 @@ public class Main {
"smoketest",
false,
"Exit Photon after loading native libraries and camera configs, but before starting up camera runners");
options.addOption("p", "platform", true, "Specify platform override, based on Platform enum");
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args);
@@ -118,6 +119,18 @@ public class Main {
if (cmd.hasOption("smoketest")) {
isSmoketest = true;
}
if (cmd.hasOption("platform")) {
String platStr = cmd.getOptionValue("platform");
try {
Platform plat = Platform.valueOf(platStr);
Platform.overridePlatform(plat);
logger.info("Overrode platform to: " + plat);
} catch (IllegalArgumentException e) {
logger.error("Invalid platform override: " + platStr);
return false;
}
}
}
return true;
}
@@ -161,6 +174,18 @@ public class Main {
VisionSourceManager.getInstance().registerLoadedConfigs(cameraConfigs);
}
private static void tryLoadJNI(JNITypes type) {
try {
LoadJNI.forceLoad(type);
logger.info("Loaded " + type.name() + "-JNI");
} catch (IOException e) {
logger.error("Failed to load " + type.name() + "-JNI!", e);
if (isSmoketest) {
System.exit(1);
}
}
}
public static void main(String[] args) {
logger.info(
"Starting PhotonVision version "
@@ -209,41 +234,24 @@ public class Main {
System.exit(1);
}
try {
if (Platform.isRaspberryPi()) {
LoadJNI.forceLoad(LoadJNI.JNITypes.LIBCAMERA);
logger.info("Loaded libcamera-JNI");
}
} catch (IOException e) {
logger.error("Failed to load libcamera-JNI!", e);
if (Platform.isRaspberryPi()) {
tryLoadJNI(JNITypes.LIBCAMERA);
}
try {
if (Platform.isRK3588()) {
LoadJNI.forceLoad(LoadJNI.JNITypes.RKNN_DETECTOR);
logger.info("Loaded RKNN-JNI");
} else {
logger.error("Platform does not support RKNN based machine learning!");
}
} catch (IOException e) {
logger.error("Failed to load RKNN-JNI!", e);
if (Platform.isRK3588()) {
tryLoadJNI(JNITypes.RKNN_DETECTOR);
} else {
logger.error("Platform does not support RKNN based machine learning!");
}
try {
if (Platform.isQCS6490()) {
LoadJNI.forceLoad(LoadJNI.JNITypes.RUBIK_DETECTOR);
logger.info("Loaded Rubik-JNI");
} else {
logger.error("Platform does not support Rubik based machine learning!");
}
} catch (IOException e) {
logger.error("Failed to load Rubik-JNI!", e);
if (Platform.isQCS6490()) {
tryLoadJNI(JNITypes.RUBIK_DETECTOR);
} else {
logger.error("Platform does not support Rubik based machine learning!");
}
try {
LoadJNI.forceLoad(LoadJNI.JNITypes.MRCAL);
logger.info("mrcal-JNI loaded successfully.");
} catch (Exception e) {
logger.warn(
"Failed to load mrcal-JNI! Camera calibration will fall back to opencv\n"
+ e.getMessage());
if (Platform.isWindows() || Platform.isLinux()) {
tryLoadJNI(JNITypes.MRCAL);
}
CVMat.enablePrint(false);