mirror of
https://github.com/Klipper4FlashForge/firmware.git
synced 2026-10-19 03:49:50 -05:00
Version the pinned recipes on the release, not on memory (#21)
apk decides whether to upgrade from the version string alone. Three recipes
pin an upstream version -- anvil-moonraker on ${MOONRAKER_VERSION#v},
anvil-klipper on the pinned commit, anvil-helixscreen on its tag -- and each
ships a payload/ of ours beside that upstream tree. Our half changes without
the string moving, so the feed serves new bytes under the name every printer
already holds and `apk upgrade` finds nothing to do. #16 did exactly that to
moonraker.conf, the file that moves Moonraker's config to
/usr/data/anvil-data/config.
PKG_RELEASE is that string's other half, and it is the release date now:
pkg_release_stamp, monotone, with the same-day letter as a trailing digit so
20260827b sorts between 20260827 and 20260828. Nobody has to notice that a
payload changed, which is the only version of this that holds.
PKG_STAMP_EXTRA="$(pkg_payload_hash)" is not this and reads as though it were.
It hashes payload/ so the BUILD rebuilds; it says nothing to a printer. All
three recipes had it, and all three would have shipped stale.
test_recipe_layout.py makes it the rule for recipes added later: a pinned
recipe with a payload/ must take pkg_release_stamp, and the failure names the
recipe and the line to write.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
5316694795
commit
5f237eff62
6 files changed
+93
-3
No files matched your search
@@ -889,6 +889,16 @@ yesterday would resolve and install yesterday's `anvil-core` without
|
||||
complaint. `patch.sh` checks for the expected filename before installing and
|
||||
names `./bin/build-packages.sh` if it is absent.
|
||||
|
||||
The recipes whose version is a **pin** have the opposite problem.
|
||||
`anvil-moonraker`, `anvil-klipper`, `anvil-helixscreen` and `anvil-timelapse`
|
||||
ship files of ours beside an upstream tree, and apk decides whether to upgrade
|
||||
from the version string alone: a change under `payload/` is new bytes under an
|
||||
old name, so a printer already holding that version keeps what it has.
|
||||
`PKG_RELEASE` is the field that moves — raise it when `payload/` changes, and
|
||||
back to 1 when the pin itself moves. `PKG_STAMP_EXTRA="$(pkg_payload_hash)"`
|
||||
is a different mechanism for a different reader: it makes *this build* notice
|
||||
the edit and rebuild. It does not make a printer notice it.
|
||||
|
||||
The model is the one fact opkg cannot work out for itself: both chamber
|
||||
configs are built every time, they own the same `config/printer.chamber.cfg`,
|
||||
and they `Conflict`. opkg refuses the pair with exit 255 — measured — so
|
||||
|
||||
@@ -13,7 +13,13 @@ PKG_NAME=anvil-helixscreen
|
||||
# this reads it. Both live there because both are the pin, and a bump has to
|
||||
# move them together.
|
||||
PKG_VERSION="$HELIX_PKG_VERSION"
|
||||
PKG_RELEASE=1
|
||||
# THE REVISION IS THE RELEASE DATE, because the version above is a pin and does
|
||||
# not move when our half of this package changes. apk upgrades on the version
|
||||
# string alone, so a hand-maintained number here is one somebody has to
|
||||
# remember; pkg_release_stamp is the release, and every printer on an earlier
|
||||
# one sees a higher -r. qa/static/test_recipe_layout.py holds recipes with a
|
||||
# payload/ to this.
|
||||
PKG_RELEASE="$(pkg_release_stamp)"
|
||||
|
||||
PKG_EXCLUDE=".version"
|
||||
|
||||
|
||||
@@ -19,7 +19,13 @@ PKG_NAME=anvil-klipper
|
||||
# that way -- `+git` parsed fine under the old packager for a year, which is
|
||||
# why nothing noticed until the format changed.
|
||||
PKG_VERSION="0.13.0~$(printf '%.8s' "$KLIPPER_VERSION")"
|
||||
PKG_RELEASE=1
|
||||
# THE REVISION IS THE RELEASE DATE, because the version above is a pin and does
|
||||
# not move when our half of this package changes. apk upgrades on the version
|
||||
# string alone, so a hand-maintained number here is one somebody has to
|
||||
# remember; pkg_release_stamp is the release, and every printer on an earlier
|
||||
# one sees a higher -r. qa/static/test_recipe_layout.py holds recipes with a
|
||||
# payload/ to this.
|
||||
PKG_RELEASE="$(pkg_release_stamp)"
|
||||
PKG_EXCLUDE=".version"
|
||||
|
||||
# THE INTERPRETER IS A DEPENDS: etc/s6-rc/source/klipper/run execs $FF_PYTHON
|
||||
|
||||
+22
@@ -50,6 +50,28 @@ pkg_payload_hash() {
|
||||
| sha256sum | cut -c1-16
|
||||
}
|
||||
|
||||
# pkg_release_stamp -> the packaging revision for a recipe whose VERSION is an
|
||||
# upstream pin but whose contents are partly this repo's.
|
||||
#
|
||||
# apk decides whether to upgrade from the version string alone, and for those
|
||||
# recipes the string does not move when our files change: anvil-moonraker is
|
||||
# `0.11.0` whatever we ship beside upstream's tree, anvil-klipper is the
|
||||
# pinned commit whatever our klippy extras say. The revision is what moves, so
|
||||
# it is the release date rather than a number somebody has to remember to
|
||||
# raise -- a printer on any earlier release sees a higher `-r` and upgrades.
|
||||
#
|
||||
# THE TRAILING LETTER IS A SAME-DAY RE-RELEASE (20260827b, and there were four
|
||||
# that day). apk compares `-r` numerically, so the letter becomes a digit
|
||||
# after the date rather than beside it: 20260827 -> 202608270, `b` ->
|
||||
# 202608272, and the next day's 202608280 is still larger. Appending the
|
||||
# letter's index without the extra place would order 20260827b above 20260828.
|
||||
pkg_release_stamp() {
|
||||
_d=${MOD_VER%%[a-z]}
|
||||
_l=${MOD_VER#"$_d"}
|
||||
printf '%s%s' "$_d" "$(awk -v l="$_l" \
|
||||
'BEGIN { print (l == "") ? 0 : index("abcdefghijklmnopqrstuvwxyz", l) }')"
|
||||
}
|
||||
|
||||
# pkg_signkey_hash -> a cache key for the feed's public key, or `unsigned`.
|
||||
#
|
||||
# anvil-core ships that key, and it lives OUTSIDE the repo, so
|
||||
|
||||
@@ -13,7 +13,13 @@ PKG_ARCH=all
|
||||
# sqlite the releases after it wanted. It builds its own CPython now, so it
|
||||
# can. apk orders 0.11.0 after every 0.8.0 string that shipped.
|
||||
PKG_VERSION="${MOONRAKER_VERSION#v}"
|
||||
PKG_RELEASE=1
|
||||
# THE REVISION IS THE RELEASE DATE, because the version above is a pin and does
|
||||
# not move when our half of this package changes. apk upgrades on the version
|
||||
# string alone, so a hand-maintained number here is one somebody has to
|
||||
# remember; pkg_release_stamp is the release, and every printer on an earlier
|
||||
# one sees a higher -r. qa/static/test_recipe_layout.py holds recipes with a
|
||||
# payload/ to this.
|
||||
PKG_RELEASE="$(pkg_release_stamp)"
|
||||
|
||||
PKG_EXCLUDE=".version"
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ legitimately changed, which is the opposite of what a test is for.
|
||||
What is left is the two that bite:
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -126,3 +127,42 @@ def test_klipper_still_depends_on_numpy():
|
||||
"lost feature -- klippy loads [stepper_resonance_tester] from "
|
||||
"FlashForge's printer.vibration.cfg and dies on the ImportError, so "
|
||||
"the printer never reaches ready.")
|
||||
|
||||
|
||||
def test_a_pinned_recipe_that_ships_our_files_versions_on_the_release():
|
||||
"""A recipe apk can never see a change in is a recipe printers never update.
|
||||
|
||||
Two kinds of recipe live under pkgs/. One versions on `$MOD_VER`, the
|
||||
release date, so every build says something new. The other pins an
|
||||
upstream version -- `${MOONRAKER_VERSION#v}`, the Klipper commit, the
|
||||
HelixScreen tag -- and that string stays put however much of OUR half of
|
||||
the package changes, because `payload/` is ours. apk compares the version
|
||||
and nothing else: same string, no upgrade, whatever the bytes say.
|
||||
|
||||
`PKG_STAMP_EXTRA="$(pkg_payload_hash)"` does not help here and reads as
|
||||
though it should. It hashes `payload/` so the BUILD rebuilds the package;
|
||||
it says nothing to a printer.
|
||||
|
||||
So a pinned recipe with a `payload/` directory takes its revision from
|
||||
`pkg_release_stamp` -- the release date, monotone, and nobody's to
|
||||
remember. This test is what makes that the rule rather than a habit.
|
||||
"""
|
||||
missing = []
|
||||
for name, d in recipes():
|
||||
if not os.path.isdir(os.path.join(d, "payload")):
|
||||
continue # ships nothing of ours to go stale
|
||||
conf = open(os.path.join(d, "pkg.conf")).read()
|
||||
version = re.search(r"^PKG_VERSION=(.*)$", conf, re.M)
|
||||
release = re.search(r"^PKG_RELEASE=(.*)$", conf, re.M)
|
||||
if version and "MOD_VER" in version.group(1):
|
||||
continue # the whole version is the release
|
||||
if not release or "pkg_release_stamp" not in release.group(1):
|
||||
missing.append("%s (PKG_VERSION=%s, PKG_RELEASE=%s)" % (
|
||||
name,
|
||||
version.group(1) if version else "?",
|
||||
release.group(1) if release else "1 (default)"))
|
||||
assert not missing, (
|
||||
"these recipes pin an upstream version and ship a payload/ of ours, so "
|
||||
"a change to our half leaves the version they had -- and no printer "
|
||||
"upgrades: %s. Set PKG_RELEASE=\"$(pkg_release_stamp)\"."
|
||||
% ", ".join(missing))
|
||||
Reference in new issue
Block a user