Feature request: custom conditional updates

We’re building some devices that sometimes run on backup battery power.

I’ve been testing the official Balena CI method via Github Actions and was thinking it would be wonderful for an easy way to set conditional updates on a device by device basis.

For example, we have a lightweight Python container that watches the power and battery status of the device. It would be cool to be able to flag the device on Balena’s side as being ineligible for update if the device is running on battery power and is below 50%.

I could imagine other scenarios that others might find useful like don’t allow updates if running on cellular as a backup interface.

The flag could be lifted the device conditions are back to normal like no longer on battery or cellular.

Hi

I think we might be able to do this using our current capabilities!

You can add a tag to the device if its under a particular level of charge, and when you are updating the devices you can select devices based on the value of that tag for every device.

The value of the tag can be updated by the devices themselves, or if you already have that telemetry information with you, you can set the value using a script on your machine instead of the device.

1 Like

@anujdeshpande so I’ve got the tagging from a script on device figured out, but what I’m unclear on is how to filter those tagged devices (eg. “battery_powered”: true & “battery_level” <= 50) from a release.

I’m using Github Actions so pull requests create a release in Balena but not deploy, and when PR is merged into master that release is marked final and release to all devices. What is the best way to use that workflow but remove devices with certain tags?

Bonus would be then for those skipped devices to automatically receive that pending update when their tag conditions change (e.g. “battery_powered”: false & “battery_level” = 100)?

Hey,
Good work on figuring out the device tags script. In order to filter which devices receive the update on a conditional basis, pinning of releases can be used on a per device basis. Here’s the workflow in my head for your use case and bonus objective.

  1. In the start, all devices are pinned on a specific release and all the devices have tags that automatically update as conditions change (using your script). From this state, a condition can be defined for when a device should update. For example: "battery_powered": false & "battery_level" = 100
  2. With your GitHub action workflow which finalizes releases from a PR and then deploys to all devices wouldn’t have any impact here since all devices are already pinned to a specific release. So new releases won’t get automatically deployed on all devices.
  3. Now, you can run a script to check tags for all devices in a fleet (using balenaSDK or API) to figure out if they match the predefined condition you have set or not.
    3.1 If the condition to update doesn’t match the tags on a device, then do nothing.
    3.2 If the condition matches, then repin that device’s release to the latest finalized release. This will start the update process for that device. Do the same check in a loop for all devices.
  4. The script can run periodically to poll the device tags on a per hour basis and repinning the device when the condition gets satisfied.

This is how we can run conditional updates on a per device basis.
The predefined condition to update or not can be left configurable by using either of the 2 setups below:

  1. Run the script locally on the device and pass the condition as a fleet variable (Not ideal, the device can be offline or in a bad state)
  2. Or, there’s a global script that could be polling device tags and repinning devices in the fleet outside of the system (recommended, can act as an agent for finer release management)

By having a global script, you can continuously monitor your devices so that they can receive pending updates when their tag conditions change.

Links & references:

Hope this helps and free feel to ask for more information if this doesn’t fit your use-case. A request, please do post your final solution in order to help others that come looking and we could probably help in optimizing API calls. It helps quite a lot. Thanks!