Vipul Gupta
Vipul is a software engineer at balena and a documentarian running his docs initiative called Mixster. He advocates strongly for open-source, cheesecakes and party parrots.
@vipulgupta2048
@vipulgupta2048
We-pull
@vipulgupta2048
@vipulgupta2048
BalenaOS runs containers on CO2 sensors, farms, smart dustbins, trucks...
First to run Docker containers in space.
@vipulgupta2048
... underwater drones, museums, photo booths, parkings, forklifts, and your talking wireless speakers
@vipulgupta2048
@vipulgupta2048
With smart cities & even your toaster getting firmware updates. The stakes have never been higher
@vipulgupta2048
@vipulgupta2048
@vipulgupta2048
@vipulgupta2048
@vipulgupta2048
Worker
(controller)
Raspberry Pi 4
(Device Under Test)
With Autokit, we enabled a Hardware in loop testing pipeline for balenaOS
@vipulgupta2048
@vipulgupta2048
@vipulgupta2048
@vipulgupta2048
Hardware in the loop testing pipeline in a nutshell
GitHub
Actions
@vipulgupta2048
The journey from PR to Production begins
@vipulgupta2048
@vipulgupta2048
A contributor opens a pull request on the balenaOS repository.
@vipulgupta2048
PR triggers multiple GitHub Actions jobs that build BalenaOS releases for each device we configure a caller workflow.
@vipulgupta2048
@vipulgupta2048
On PR open: Build + Test jobs
On Closed: Build + Deploy (Releases already tested)
On Dispatch: Whatever you desire.
@vipulgupta2048
Intel-NUC calls the big composite workflow, controls triggers, inputs, external contributor access & secrets
Artifacts built by the build job are uploaded to GH Artifact Storage to be downloaded in test jobs managed by our testing framework, Leviathan.
@vipulgupta2048
@vipulgupta2048
Leviathan is the software layer that interacts with balenaOS images, does configuration and talks to our Intel-NUC device under test connected to hardware jig, autokit.
@vipulgupta2048
@vipulgupta2048
Leviathan abstracts away complexities by enabling developers to write one test suite to target all devices.
No matter their power requirements, boot process, or flash procedure. Leviathan takes care of everything.
// Leviathan test to flash a device connected to the autokit (Sample)
await this.worker.off(); // Ensure test device is off before flashing
await this.worker.flash(this.os.image.path); // Flash the device with balenaOS image
await this.worker.on(); // Turn on the device
test.true(
true,
`${this.os.image.path} should be flashed properly`,
);
@vipulgupta2048
Workers automatically provision the device under test with the OS, provides power, network & executes our commands
@vipulgupta2048
@vipulgupta2048
[
{
"suite": "Managed BalenaOS release suite",
"stats": {
"tests": 12,
"ran": 10,
"skipped": 2,
"passed": 10,
"failed": 0
},
"tests": {
"Image preload test": "passed",
"Move device to hostapd test App": "skipped",
"Move device back to original app": "skipped",
"Provisioning without deltas": "passed",
"Override lock test": "passed",
"Update supervisor randomized timer": "passed",
"Set device environment variables": "passed",
"Set service environment variables": "passed",
"SSH authentication in production mode": "passed",
"SSH authentication in development mode": "passed",
"os-config service on boot": "passed",
"os-config service randomized timer": "passed"
},
"dateTime": "Thu Apr 27 2023 11:43:52 GMT+0000 (Coordinated Universal Time)"
},
{
"suite": "Hostapp update suite",
"stats": {
"tests": 5,
"ran": 5,
"skipped": 0,
"passed": 5,
"failed": 0
},
"tests": {
"Broken balena-engine": "passed",
"Broken VPN": "passed",
"Rollback altboot (broken init) test": "passed",
"HUP from previous release": "passed",
"HUP from this release": "passed"
},
"dateTime": "Thu Apr 27 2023 11:58:25 GMT+0000 (Coordinated Universal Time)"
},
{
"suite": "Unmanaged BalenaOS release suite",
"stats": {
"tests": 45,
"ran": 36,
"skipped": 9,
"passed": 36,
"failed": 0
},
"tests": {
"check secure boot": "passed",
"BeagleBone Black u-boot overlay test: deactivate HDMI": "skipped",
"243390-rpi3 - CUS/EUS chipsets test": "skipped",
"fingerprint file test": "passed",
"ext4 filesystems are checked on boot": "passed",
"OS-release file check": "passed",
"Installer used migrator module": "passed",
"issue file check": "passed",
"issue.net file check": "passed",
"Chronyd service": "passed",
"Sync test": "passed",
"Source test": "passed",
"Offline sources test": "passed",
"System time skew test": "passed",
"kernel-overlap test": "passed",
"Bluetooth scanning test": "skipped",
"Container healthcheck test": "passed",
"Container exposed variables test": "passed",
"Identification test": "skipped",
"Cellular tests": "passed",
"hostname configuration test": "passed",
"ntpServer test": "passed",
"dnsServers test": "passed",
"os.network.connectivity test": "passed",
"os.network.wifi.randomMacAddressScan test": "passed",
"udevRules test": "passed",
"persistentLogging configuration test": "passed",
"Reboot test": "skipped",
"Wired test": "skipped",
"Wireless test": "skipped",
"Socks5 test": "passed",
"Http-connect test": "passed",
"Engine socket is exposed in development images": "passed",
"Engine socket is not exposed in production images": "passed",
"Engine watchdog recovery": "passed",
"Engine healthcheck performance": "passed",
"Under-voltage test": "passed",
"Ramdisks, zram and loop devices are not scanned for rootfs": "passed",
"by-state links are created": "passed",
"DToverlay & DTparam tests": "skipped",
"state partition reset": "passed",
"data partition reset": "passed",
"RevPi Core 3 DIO module test": "skipped",
"zram is enabled and configured as swap": "passed",
"Internet sharing iptables rules test": "passed"
},
"dateTime": "Thu Apr 27 2023 11:24:52 GMT+0000 (Coordinated Universal Time)"
}
]
@vipulgupta2048
[
{
"suite": "Managed BalenaOS release suite",
"stats": {
"tests": 12,
"ran": 10,
"skipped": 2,
"passed": 10,
"failed": 0
},
"tests": {
"Image preload test": "passed",
"Move device to hostapd test App": "skipped",
"Move device back to original app": "skipped",
"Provisioning without deltas": "passed",
"Override lock test": "passed",
"Update supervisor randomized timer": "passed",
"Set device environment variables": "passed",
"Set service environment variables": "passed",
"SSH authentication in production mode": "passed",
"SSH authentication in development mode": "passed",
"os-config service on boot": "passed",
"os-config service randomized timer": "passed"
},
"dateTime": "Thu Apr 27 2023 11:43:52 GMT+0000 (Coordinated Universal Time)"
},
{
"suite": "Hostapp update suite",
"stats": {
"tests": 5,
"ran": 5,
"skipped": 0,
"passed": 5,
"failed": 0
},
"tests": {
"Broken balena-engine": "passed",
"Broken VPN": "passed",
"Rollback altboot (broken init) test": "passed",
"HUP from previous release": "passed",
"HUP from this release": "passed"
},
"dateTime": "Thu Apr 27 2023 11:58:25 GMT+0000 (Coordinated Universal Time)"
},
{
"suite": "Unmanaged BalenaOS release suite",
"stats": {
"tests": 45,
"ran": 36,
"skipped": 9,
"passed": 36,
"failed": 0
},
"tests": {
"check secure boot": "passed",
"BeagleBone Black u-boot overlay test: deactivate HDMI": "skipped",
"243390-rpi3 - CUS/EUS chipsets test": "skipped",
"fingerprint file test": "passed",
"ext4 filesystems are checked on boot": "passed",
"OS-release file check": "passed",
"Installer used migrator module": "passed",
"issue file check": "passed",
"issue.net file check": "passed",
"Chronyd service": "passed",
"Sync test": "passed",
"Source test": "passed",
"Offline sources test": "passed",
"System time skew test": "passed",
"kernel-overlap test": "passed",
"Bluetooth scanning test": "skipped",
"Container healthcheck test": "passed",
"Container exposed variables test": "passed",
"Identification test": "skipped",
"Cellular tests": "passed",
"hostname configuration test": "passed",
"ntpServer test": "passed",
"dnsServers test": "passed",
"os.network.connectivity test": "passed",
"os.network.wifi.randomMacAddressScan test": "passed",
"udevRules test": "passed",
"persistentLogging configuration test": "passed",
"Reboot test": "skipped",
"Wired test": "skipped",
"Wireless test": "skipped",
"Socks5 test": "passed",
"Http-connect test": "passed",
"Engine socket is exposed in development images": "passed",
"Engine socket is not exposed in production images": "passed",
"Engine watchdog recovery": "passed",
"Engine healthcheck performance": "passed",
"Under-voltage test": "passed",
"Ramdisks, zram and loop devices are not scanned for rootfs": "passed",
"by-state links are created": "passed",
"DToverlay & DTparam tests": "skipped",
"state partition reset": "passed",
"data partition reset": "passed",
"RevPi Core 3 DIO module test": "skipped",
"zram is enabled and configured as swap": "passed",
"Internet sharing iptables rules test": "passed"
},
"dateTime": "Thu Apr 27 2023 11:24:52 GMT+0000 (Coordinated Universal Time)"
}
]
@vipulgupta2048
Breaking things intentionally to see if the OS can recover & update
@vipulgupta2048
@vipulgupta2048
The jobs are completed in their own time, and statuses are updated back on the pull request to be reviewed by the team to see what's going on.
The jobs are completed in their own time, and statuses are updated back on the pull request to be reviewed by the team to see what's going on.
@vipulgupta2048
<<<<
After all required checks pass, & PR gets approved,
it gets merged automatically.
@vipulgupta2048
The closed event trigger re-runs BalenaOS builds, and pushes them to S3 with the required artifacts. All using GitHub Actions. They show up here to be used by our users.
@vipulgupta2048
GitHub Actions builds +1000 balenaOS releases daily
and runs +3000 test jobs.
@vipulgupta2048
Reliability, reusablity, context retrieval & transparency of logs
*Also, why we are migrating from Jenkins
@vipulgupta2048
Ease of getting started: Using either GitHub's hosted runners or...
*Also, does help that this exists ✨
@vipulgupta2048
BYOR: Bring your own runners! Cost savings 💸💸💸
*Also, does help that this exists ✨
@vipulgupta2048
Setting up environments for testing, staging, and prod
*Also, does help that this exists ✨
@vipulgupta2048
This is hardware in loop testing with Jenkins
With Hardware in Loop Testing & Jenkins for CI/CD, we have managed to:
Most importantly, we even added QEMU support for testing virtual devices. Thanks to the Chip Shortage 2022
Worker
(controller)
Remote devices must be directly controlled, automated, and maintained using scripts.
@vipulgupta2048
Worker
(controller)
Feedback on changes
Testing software directly on hardware
in a CI/CD pipeline
@vipulgupta2048
?
Worker
(controller)
?
?
?
?
?
?
?
?
?
?
?
Quality Assurance, stress testing, random testing, environmental testing
@vipulgupta2048
@vipulgupta2048
@vipulgupta2048
@vipulgupta2048
Questions? Collaborate? Work with us? Reach out!
@vipulgupta2048
Reviews cheesecakes, closes issues & runs Mixster to "right" the docs for startups
Feedback please + Link to the slides
By Vipul Gupta
This presentation is about using GitHub Actions to test hundreds of OS images, specifically focusing on balenaOS and the challenges of testing embedded operating systems. The talk is about balenaOS's build, testing, and deployment pipelines using GitHub Actions that took place at GitHub Constellation 2024 in Bangalore, India.
Vipul is a software engineer at balena and a documentarian running his docs initiative called Mixster. He advocates strongly for open-source, cheesecakes and party parrots.