Package version improvements - #102
Draft
Christopher Obbard (obbardc) wants to merge 9 commits into
Draft
Conversation
Christopher Obbard (obbardc)
had a problem deploying
to
Staging
September 4, 2026 15:58 — with
GitHub Actions
Error
Christopher Obbard (obbardc)
had a problem deploying
to
Staging
September 4, 2026 15:59 — with
GitHub Actions
Error
Christopher Obbard (obbardc)
had a problem deploying
to
Staging
September 4, 2026 16:00 — with
GitHub Actions
Error
Christopher Obbard (obbardc)
had a problem deploying
to
Staging
September 4, 2026 16:00 — with
GitHub Actions
Error
systemd-boot sorts boot entries on the BLS 'version' key, which kernel-install writes verbatim from uname -r. Under systemd's version comparison: 7.2.0-rc7-qcom-next-20260821 > 7.2.0-qcom-next-20260826 so every release candidate outranked the final release that followed it, and an rc daily stayed the default boot entry after the release was installed. The deciding comparison is a plain strcmp of "rc" against "qcom", where 'r' > 'q'; there is no notion of a pre-release involved. debian/rules already rewrites -rcN to ~rcN, but only for the Debian version, because a package name may not contain '~' and the binary packages are named linux-image-<KVER>. So dpkg ordered these correctly all along and only the boot menu was wrong. Joining the suffix with '+' fixes it: systemd compares the separator before the chunk behind it, and '-' < '+'. This is not a local invention -- it is why Debian's own kernels sort correctly (linux-image-7.1.10+deb14-amd64). Upstream bindeb-pkg has the identical ~rc/-rc split and gets away with it for a different reason: it puts a numeric commit count in that slot, and systemd ranks digits above letters. qcom-next was the only scheme putting a lowercase word there. The Debian version is unchanged, byte for byte: DATE_PART reads the date off the end of LOCALVERSION, which still matches. Only uname -r and the binary package names change. Note this renames every binary package. Already-installed kernels under the old names are not upgraded or removed by it -- they keep their existing sort position until purged, so the fix applies to newly installed kernels only. Signed-off-by: Christopher Obbard <chris.obbard@oss.qualcomm.com>
The stub was a bare '0qli', which left a packaging-only rebuild -- same kernel snapshot, changed debian/ -- with no field to bump. Neither of the other two components can absorb it: suite_suffix_mapping is a per-suite constant shared by every row, and the delivery suffix is the Daily/Release marker. Bumping either to force a rebuild through would corrupt what they mean. Make the trailing digit part of the stub, so a rebuild is 0qli1 -> 0qli2 and lands uniformly across every suite: 0qli1~bpo13+1~ < 0qli1~bpo13+1 < 0qli2~bpo13+1 derive-debian-revision.sh now rejects a stub that does not end in a digit, alongside the existing "must not end in ~" check. Both guard the same thing: a stub that quietly loses a field it is supposed to carry. Signed-off-by: Christopher Obbard <chris.obbard@oss.qualcomm.com>
debian/rules recovered the snapshot date by matching the tail of
LOCALVERSION, a string it did not build and cannot safely parse. The variant
name in the middle is caller-supplied and unbounded, and a branch-tip suffix
ends in a 12-hex SHA that can be eight digits:
$ echo '+qcom-next-g123456789012' | grep -oE '[0-9]{8}$'
56789012
Such a build was versioned 7.2.0~rc7+56789012-0qli1, naming a snapshot date
that never existed and sorting it against real ones. Roughly one branch-tip
SHA in ten ends that way, so this is a live bug, not a theoretical one.
Anchoring the match would have fixed those refs while leaving the guess in
place. Carry the field instead. derive-localversion.sh already knows the
snapshot -- it matched the tag to build LOCALVERSION in the first place -- so
it now emits both:
LOCALVERSION=+qcom-next-20260722
SNAPSHOT=20260722
KEY=VALUE because the workflow appends them straight to GITHUB_ENV.
prepare-source.sh gains --snapshot and forwards it, and its tag auto-detect
derives both fields in one match. debian/rules takes SNAPSHOT as an input and
validates its shape rather than discovering it.
Neither caller reconstructs the field when it is absent. An explicit
--localversion replaces the derived suffix precisely because the ref no
longer describes the build, so parsing it back would reinstate the guess this
commit removes. Both paths warn that the Debian version will carry no dated
component, which is visible and correctable, unlike a date invented from a
SHA.
Signed-off-by: Christopher Obbard <chris.obbard@oss.qualcomm.com>
A second tag cut on the same day (qcom-next-7.2-20260826.1) collapsed onto the same version as the first, because every derivation matched only a bare YYYYMMDD. derive-localversion.sh dropped the ordinal; prepare-source.sh matched trailing digits with -([0-9]+)$, which a ".1" suffix cannot satisfy at all, so the tag fell through to the +<whole-tag> fallback. Match the date width explicitly with an optional ordinal after it, so the component stays whole: qcom-next-7.2-20260826 -> +qcom-next-20260826 / 20260826 qcom-next-7.2-20260826.1 -> +qcom-next-20260826.1 / 20260826.1 The first tag of a day deliberately keeps the plain form rather than normalising to ".0". Both comparators read an absent ordinal as lower than a present one, so the respin already sorts above it and every other build is spared a ".0" it never needed. Signed-off-by: Christopher Obbard <chris.obbard@oss.qualcomm.com>
The dated component was appended bare, as +20260722, which reads as part of the upstream version rather than as a snapshot marker. Debian spells a VCS snapshot +git<date>, so use that: 7.2.0~rc3+git20260722-0qcom1 7.2.0~rc3+git20260722.1-0qcom1 Ordering is unchanged -- the 'git' is a constant prefix on both sides of every comparison, and the date behind it still decides. Signed-off-by: Christopher Obbard <chris.obbard@oss.qualcomm.com>
The snapshot date identifies the tag, not the commit the tag pointed at when the build was cut. A moved tag then produces two different kernels under one version, indistinguishable in the archive and on a running system. Append the commit to both strings: uname -r 7.2.0-rc7+qcom-next-20260826.1-gabcdef123456 Debian version 7.2.0~rc7+git20260826.1~gabcdef123456-0qli1~bpo13+1 The separators differ, and the difference is load-bearing rather than sloppy. systemd weighs the separator before the chunk behind it, so '-g<sha>' leaves an absent respin ordinal sorting below a present one. dpkg instead alternates digit and non-digit runs and reads an exhausted run as lower than a letter, so the same '.' or '-' join would decide before reaching the ordinal: 7.2.0+git20260826.g3f2f3ca1a81e > 7.2.0+git20260826.1.gabcdef123456 putting a respin below the build it respins. '~' sorts below everything including the empty string, so the ordinal is always compared first and the SHA only ever breaks a tie between builds sharing a snapshot. The alternative -- spelling ".0" on every non-respin build -- buys the same ordering at the cost of a redundant ordinal in every version forever. What '~' costs is one reading: the version sorts below the same snapshot without a SHA, as though it preceded it. Nothing occupies that slot, because every snapshot build carries a SHA, so the claim is never tested against a real version. The SHA cannot order anything -- two SHAs have no relation -- so a moved tag still needs its respin ordinal or the packaging revision bumped before users can upgrade onto it. What this buys is that the two builds are never confused for each other. --sha becomes required for every build rather than just branch tips, and is validated as hex, since it is now part of every kernel release rather than a fallback identity for refs that had nothing else. Signed-off-by: Christopher Obbard <chris.obbard@oss.qualcomm.com>
(cherry picked from commit d6c478d, reworked)
A branch-tip build had no snapshot, so debian/rules emitted a version with no
+git<date> at all -- 7.2.0~rc7-0qli1~bpo13+1 -- which sorts below every dated
build rather than among them. Take the date from the HEAD commit instead, so
these builds land in the same sequence:
7.2.0~rc7+git20260821~g07f50dc44edd-… tag build
7.2.0~rc7+git20260904~g07f50dc44edd-… branch tip, dated by commit
The date is the committer date of HEAD, not the build date:
- rebuilding a commit reproduces its version instead of inventing a higher
one on each run
- the date describes the source rather than when CI happened to run
- it lands in the same space as upstream's tag dates, which track the
commit each tag is cut from
Committer date rather than author date, because an author date can be months
old on a backported patch. Normalised to UTC, since --date=short would
otherwise render in each committer's timezone and make one commit yield
different dates.
The trade-off is that a commit date need not advance: rewinding the branch to
an older commit produces a lower version that apt will not offer as an
upgrade. Documented in derive-localversion.sh rather than left to be found.
The original replaced --sha with --date, because at the time the SHA was not
in the version and dating a build meant giving up identifying it. Both are
kept here: --sha is required for every build and --date only supplies what a
branch tip's ref cannot, so a branch-tip release now has the same shape as a
tag build rather than a second shape of its own.
Signed-off-by: Christopher Obbard <chris.obbard@oss.qualcomm.com>
(cherry picked from commit d6c478d, reworked) @gitclone@ and @Branch@ were substituted with empty strings, so every changelog carried a bare "* Source:" naming nothing. Thread the clone URL, ref and full SHA through prepare-source.sh so the entry says where the build came from: * Source: https://github.com/qualcomm-linux/kernel qcom-next * Commit: 07f50dc44edd… The original justified this as the only place the exact source was pinned, since LOCALVERSION identified a build by date alone. That is no longer true -- the version strings carry the commit -- but the repository and ref are still nowhere else, and a 12-character abbreviation is not the commit itself. The comments asserting otherwise are corrected rather than carried over. prepare-source.sh gains one --git-sha taking the full SHA, not two. The original added a second option under that name for the changelog, alongside the existing one for the version field; bash takes the first matching case arm, so the changelog copy would have been silently unset and every entry would have read "Commit: unknown". They are the same commit at two widths, so the short form is derived from the long one in a single place. Signed-off-by: Christopher Obbard <chris.obbard@oss.qualcomm.com>
Records why the kernel release and the Debian version are two strings rather than one, and why each spells the same four fields differently: the '+' join that keeps a release candidate below its final release under systemd, and the '~' before the SHA that keeps a respin above the build it respins under dpkg. Both separators look arbitrary and both are load-bearing, so the reasoning is written down where someone tempted to normalise them will find it. Also covers what the version deliberately does not carry -- the repository and ref live in the changelog -- and the one case where a branch-tip version can go backwards, when the branch is rewound to an older commit. README.md loses its copy of the same reasoning, which had grown into a second account that would drift, and keeps the format table plus a pointer here. Scoped to qcom-next; the derivation is not variant-agnostic. Signed-off-by: Christopher Obbard <chris.obbard@oss.qualcomm.com>
Christopher Obbard (obbardc)
force-pushed
the
wip/obbardc/version-improvements
branch
from
September 4, 2026 16:32
b4ec130 to
9e9b9d9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Improve the package versioning to allow for future expansion.
Remaining:
branch-tipbuilds.respintag works fine.uname -randsystemd-bootmenu generation.