Yocto Upstream Version Checks: Distinguish an Undiscovered Release from an Up-to-Date Recipe
A recipe can fetch its pinned source successfully while the upstream checker fails to discover a newer release. These operations ask different questions: whether the selected input is available, and whether release discovery can find and classify another version. A successful build does not answer the second question.
This analysis uses Yocto Project 5.0.12 documentation and the corresponding Poky yocto-5.0.12 source tag. Examples are synthetic. No recipe check, upstream package query, metadata change, upgrade or build was executed.
Identify the discovery input
Record the recipe’s effective PV, SRC_URI, SRCREV, and upstream-check overrides before interpreting a result. The pinned recipe utility assumes the first SRC_URI entry identifies the upstream source. A successful fetch of several recipe inputs does not establish that this first entry is suitable for release discovery.
The classifier also has special handling for recipes without source URIs, local-file sources and manually supplied upstream versions. Keep those cases separate from the ordinary remote-source investigation described here. A matching result must be interpreted against the path that produced it.
For tarballs, the variable reference describes discovery through the directory listing containing the archive. A server can serve a known archive without exposing a usable listing. UPSTREAM_CHECK_URI selects another discovery page, while UPSTREAM_CHECK_REGEX changes extraction from that page. Neither change alone proves that the intended package’s releases were selected.
Inspect version extraction before comparing versions
The Git fetcher’s release-check path scans remote tags and extracts the named pver group. It compares extracted versions, rather than treating the most recently created tag as the newest release.
Consider hypothetical lightweight tags samplelib-v1.4, samplelib-v1.6, otherlib-v99.0, and samplelib-v2.0-beta1. For this invented naming convention, a focused pattern could be:
UPSTREAM_CHECK_GITTAGREGEX = "^samplelib-v(?P<pver>[0-9]+([.][0-9]+)*)$"
The intended extracted stable candidates are 1.4 and 1.6. This is a reasoning fixture, not reported command output. Real repositories need checks for their own naming conventions and tag forms; do not copy the pattern without reviewing them.
The pinned fetcher additionally rejects tags containing lowercase alpha, beta, rc, or final before applying the version pattern. A custom pattern does not bypass that built-in filter. Consequently, an upstream naming convention containing final deserves inspection even if a maintainer regards that tag as a stable release.
When upstream does not publish version tags, UPSTREAM_CHECK_COMMITS = "1" selects commit comparison with SRCREV. A newer commit is a different discovery outcome from a stable release. Changing the recipe to AUTOREV is not a repair for release monitoring.
Preserve the classifier’s uncertainty
The pinned _get_recipe_upgrade_status function distinguishes these cases. Assume the current normalized version is 1.4, and compare an unset UPSTREAM_VERSION_UNKNOWN with the explicit value "1":
- No discovered version, or only an older version:
UNKNOWN_BROKENwhen unset, andUNKNOWNwhen declared unknown. - A discovered
1.4:MATCHwhen unset, andKNOWN_BROKENwhen declared unknown. - A discovered
1.6:UPDATEwhen unset, andKNOWN_BROKENwhen declared unknown.

An unknown declaration therefore acknowledges a discovery limitation; it does not disable checking or turn failure into a match. If discovery starts producing a matching or newer version, the declaration itself requires review. The implementation tests the variable’s truth value, so the string "0" is not equivalent to leaving it unset.
Here, BROKEN belongs to the discovery/status metadata. It is not evidence that the recipe failed to compile. Equally, MATCH establishes agreement with the candidate the configured mechanism found; it does not certify that every upstream release was visible or eligible.
Read the command output against the implementation
The 5.0.12 quick reference describes check-upgrade-status as printing recipes with newer upstream versions. The corresponding command implementation is more precise: by default it prints every result whose status is not MATCH, including unknown and broken states. Its --all option also includes matches.
Do not collapse those rows into an upgrade count. Preserve the status, current version, discovered candidate and returned revision as separate fields. Missing rows or incomplete output also require checking invocation scope and diagnostics before declaring an entire layer current.
Hand off a candidate, not an approval
If a release is discovered but intentionally deferred, record the adoption constraint using RECIPE_NO_UPDATE_REASON. That explanation is separate from an inability to determine the upstream version. An ABI migration, dependency change or product qualification requirement should not be disguised as unknown discovery.
The useful maintenance record contains the checked recipe identity, discovery endpoint or tag rule, extracted version, returned revision, status and any adoption hold. Only then does the separate upgrade workflow evaluate source changes, patches and compatibility. Discovering a candidate neither selects it for the image nor proves it is safe to adopt.