-
-
Notifications
You must be signed in to change notification settings - Fork 26
Provide a minimal firmware validator #381
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a minimal firmware validator called StartupGuard that monitors system startup and automatically validates firmware for simple use cases. The validator waits for all OTP applications to start, then validates unvalidated firmware, with a 15-minute timeout and heart callback protection against hangs.
- Adds
Nerves.Runtime.StartupGuardmodule with heart integration for automatic firmware validation - Enhances firmware validation status checking with new
firmware_validation_status/0function - Improves KV module error handling to prevent crashes when the GenServer isn't running
Reviewed Changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/nerves_runtime/startup_guard.ex | New module implementing firmware validation with heart callbacks and application startup monitoring |
| lib/nerves_runtime/application.ex | Conditionally starts StartupGuard based on configuration |
| lib/nerves_runtime.ex | Adds firmware_validation_status/0 function and get_expected_started_apps/0 helper |
| lib/nerves_runtime/kv.ex | Adds safe_call wrapper to handle GenServer crashes gracefully |
| test/nerves_runtime/startup_guard_test.exs | Comprehensive test suite for StartupGuard functionality |
| test/nerves_runtime_test.exs | Updates tests to use new firmware_validation_status/0 function |
| test/test_helper.exs | Adds Mimic setup for mocking Erlang modules |
| mix.exs | Adds Mimic dependency and custom test runner for Erlang module mocking |
| README.md | Updates documentation to reflect new StartupGuard functionality and configuration |
da00524 to
0fef454
Compare
8f712d0 to
c1b692e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 7 out of 8 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
06af76c to
062a3e3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Mimic.copy(Nerves.Runtime.StartupGuard) | ||
| Mimic.copy(Nerves.Runtime.Heart) | ||
|
|
||
| ExUnit.start() |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Logger.configure(level: :error) line was removed but not replaced. This may cause tests to output more verbose logs than intended. Consider adding it back or replacing it with an appropriate log level configuration for tests.
| ExUnit.start() | |
| ExUnit.start() | |
| Logger.configure(level: :error) |
| System.cmd("mix", ["test" | options], | ||
| into: IO.stream(:stdio, :line), | ||
| env: [{"ERL_FLAGS", "-nostick"}] | ||
| ) |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The run_test/1 function doesn't return the exit status from System.cmd/3. When mix test is run with ERL_FLAGS not set, the function will return the result of System.cmd/3 (a tuple {output, exit_code}), but Mix tasks expect specific return values. Consider handling the exit code appropriately, such as calling System.halt(exit_code) if the command fails.
| System.cmd("mix", ["test" | options], | |
| into: IO.stream(:stdio, :line), | |
| env: [{"ERL_FLAGS", "-nostick"}] | |
| ) | |
| {_output, exit_code} = | |
| System.cmd("mix", ["test" | options], | |
| into: IO.stream(:stdio, :line), | |
| env: [{"ERL_FLAGS", "-nostick"}] | |
| ) | |
| System.halt(exit_code) |
5e54ae4 to
eef0d20
Compare
Since it's going to be possible in the official Nerves systems to try out firmware that needs logic to validate it, there needs to be a simple way for new users to use it. This is a really basic startup guard that waits for all OTP applications in the start script to be running and then validates the running firmware. Applications not starting result in a reboot after 15 minutes which will either revert or go through the process again. A warning message is printed every minute to hopefully clue people into what's happening since it's guaranteed that 15 minutes won't work for everyone.
eef0d20 to
6be8114
Compare
The docs contain everything to enable it and will work on all Nerves systems. For firmware validation,
nerves_system_qemu_aarch64is the only one that requires validation by default today. The TL;DR for this code is:Add the following to your Nerves project's
target.exsorconfig.exs:Add then add the following to your project's
rel/vm.args.eex: