Skip to content

Trigger sources

A support matrix only stays current if new versions are noticed. Trigger detection is pluggable in the same way as publishing: each detector watches one kind of source, and all of them feed the same queue.

Trigger sourcesPluggable detectors - a scheduled image check, a GitHub releases watcher, a vendor page check and manual requests - emit candidate versions. A version ledger filters out anything already seen, and new triggers go to the framework.Scheduled image checkCron: latest image per OSGitHub releases watcherTags and releases via APIVendor page checkRelease notes, changelogsManual requestSpecific combinationsVersion ledgerAlready seen?Drop duplicatesTrigger queueOne per new versionFramework runProvision, test, publishAutomatic detectorsManual and runsFramework

Detector types

Detector Runs Watches Typical triggers
Scheduled image check Cron, e.g. daily The cloud provider's image catalogue A newer machine image for a supported OS, version and architecture
GitHub releases watcher Cron (webhooks only work for repositories you control) Releases and tags of upstream projects A new product agent or CLI version, Kubernetes, container runtimes, network plugins, Helm charts
Vendor page check Cron Release notes and changelog pages Vendors that publish versions only as web pages
Manual request On demand An engineer or customer-facing team Specific combinations, or a customer's exact environment

What was built, and what's design

The original framework had two automatic detectors, both running on a schedule: a scheduled image check for new OS images, and a GitHub version check for new agent and CLI releases. Specific combinations were requested manually. The version ledger, the vendor page check and the common detector interface on this page are the design I'd build on top of that today.

Detectors ran on a schedule through the CI system, the neutral entry point across clouds. When the ledger finds something new, the detector starts a run through the CI system's API, so it looks exactly like any other run.

Scheduled image check

The most useful detector for host and node topologies. On a schedule, it runs the same image resolution the framework uses at provisioning time: for each supported OS, version and architecture, find the newest published image. If the result differs from the last image tested, that's a trigger.

Reusing the resolver means detection and provisioning always agree on what "latest" means.

GitHub releases watcher

Most of the components in a cloud-native support matrix publish their releases on GitHub, including Kubernetes, container runtimes, network plugins and Helm charts, and often the product's own agent or CLI. The watcher asks the GitHub releases and tags API for each repository in its watch list, and compares the newest stable version with the last one seen.

A few rules keep this detector useful:

  • Filter pre-releases (-rc, -beta, -alpha) unless the matrix tracks them deliberately.
  • Compare versions as versions, not strings, so 1.10 sorts after 1.9.
  • Authenticate to avoid low anonymous rate limits, and use conditional requests so unchanged repositories cost nothing.

Vendor page check

The fallback for vendors without an API or feed: fetch a release notes or changelog page and extract version numbers. It's the most fragile detector, because a page redesign can break it silently. Give it an alert for when it finds nothing at all, not just for when it finds something new.

The version ledger

Every detector reports candidates, and the ledger decides which ones become triggers:

  • it stores the last version seen for each source and axis, such as ubuntu 24.04 arm64 or container-runtime;
  • it drops candidates it has already seen, so a daily check doesn't re-run the same image every day;
  • it records when each version was first seen, which also shows how long a release waited before being validated.

A small key-value table or a JSON file in object storage is enough.

One interface per detector

class Detector(Protocol):
    name: str
    def candidates(self) -> list[Candidate]: ...   # what this source says is current

The scheduler runs each detector, passes its candidates through the ledger, and turns anything new into a trigger with the same structure as a manual request. Adding a new source means writing one detector. The framework, topologies and publishing don't change.

Choosing what to detect

Detect automatically Leave to manual requests
Axes that release often and predictably (OS images, the product's own agent or CLI) Rare or customer-specific combinations
Components customers upgrade without asking Components that need a judgement call about scope
Sources with an API or a stable feed Sources that are only on web pages and change layout often