Skip to main content
A plugin lives across many host versions and many of its own versions. Semver gives operators a way to predict what an upgrade will and will not change.

Semver for plugins

Use MAJOR.MINOR.PATCH: The rule of thumb: an operator running an old config on a new MINOR version should see a working plugin. A new MAJOR version warrants reading the changelog.

Compatibility ranges

The manifest declares which host versions it supports:
The host parses each range as comma-separated atoms, where every atom is an operator followed by a semver. The supported operators: Combine atoms with a comma (logical AND): ">=0.10.0,<1.0.0". A bare semver with no operator means exact match. The pre-release and build suffixes are stripped before comparison, so 1.2.3-rc.1 compares as 1.2.3. Caret (^) and tilde (~) shorthand are not supported; write the bounds out explicitly. supported_boards is matched as an exact board-id list. The default is an empty list, which means any board. To restrict the plugin, list the exact board ids it runs on; there is no wildcard, so an empty list (or omitting the field) is the way to mean “any board”. The compatibility check runs at install time. If the running agent version is outside ados_version, the install (or the install of a newer archive over an existing plugin) is rejected. A gcs_version range is checked on the Mission Control side against the running build.

ados_version vs gcs_version

ados_version matches the running ADOS Drone Agent version (reported by setup status or /api/version). gcs_version matches the running Mission Control build. They move independently, so a plugin can support a wide agent range and a narrow GCS range or vice versa. The compatibility block and its ados_version field are both required on every manifest, even for a GCS-only plugin. Set ados_version to the agent range the plugin needs (or a wide range if it does not depend on a specific agent). gcs_version is optional; omit it for an agent-only plugin. The agent host enforces ados_version at install; Mission Control enforces gcs_version against its own build.

Update flow

  1. Operator drops a newer .adosplug into the install dialog for an already-installed plugin.
  2. The host parses the archive. If the new version’s compatibility range does not match the running host, the update is rejected.
  3. The host diffs the new manifest’s permissions against the existing grants:
    • Removed permissions: silently dropped.
    • Added optional permissions: shown with an off-by-default toggle.
    • Added required permissions: shown with emphasis; the operator must approve.
  4. The operator clicks Install. The host stops the running plugin, removes the old install directory, unpacks the new archive, regenerates the systemd unit, and re-runs the permission grants.
  5. On the next start the plugin’s lifecycle hooks run in order (on_install, on_enable, on_configure, on_start). Read your live config through ctx.config_kv and migrate your data directory if needed.
The whole flow is one click for additive updates, plus a confirmation when a new required permission is involved.

Additive vs breaking permission changes

Additive (MINOR safe):
  • Adding an optional permission.
  • Adding a slot contribution.
  • Adding a config field with a default value.
Breaking (MAJOR required):
  • Adding a required permission.
  • Removing a slot the operator depends on.
  • Renaming a config field without a migration.
  • Changing the wire format of a plugin.<id>.* event topic.
  • Changing default behavior in a way the operator would notice.

Config migration

Carry a version field in your config and migrate forward inside on_configure:

Data migration

There is no SDK migration helper. Carry a version marker in your data directory and migrate forward on start, handling skipped versions:
Forward migration is the contract; reading new data with an older plugin is best-effort.

Downgrades

Reinstalling an older version on top of a newer one is not the supported path. To roll back, remove the plugin and install the older version. The data directory persists across remove, so your data survives the rollback (your migration code still has to tolerate it).

Pre-release versions

Pre-releases use semver pre-release identifiers (1.0.0-rc.1). Treat a pre-release as older than its equivalent release, so 1.0.0 supersedes 1.0.0-rc.1. Do not ship -rc builds to operators who did not ask for them; the local-install path will happily take one.

Communicating breaking changes

A MAJOR version is contract-breaking. Update the README with a migration section, optionally ship a one-shot migration path that imports old state into the new format, and bump ados_version if the change required a new host feature. The host does not detect “user data lost” on upgrade; that responsibility is the plugin author’s.

See also