Files
firmware/test.env.example
Oleksandr ShyshatskyiandClaude Opus 5 56b5b6c334 The printer image is the only replica; make rootfs was a second way nothing took
`make rootfs` unsquashed rootfs.squashfs out of the stock package into
work/rootfs, and a thin container bind-mounted it with PROG_DUMP supplying
/usr/prog from the factory image. Every caller set PRINTER_IMAGE anyway --
both workflows wrote it into test.env BEFORE running `make rootfs`, so CI
unpacked a 93MB package, unsquashed a rootfs and downloaded a 182MB factory
image on every push and read none of it. build-printer-image.sh never used
work/rootfs either: Dockerfile.full does its own extraction from the same
public firmware and needs no stock package at all.

So the fallback went, and PROG_DUMP with it -- it was only ever read when the
replica was built locally, and both implementations already passed it empty
otherwise. Gone: the target, extract-rootfs.py, gates.extract_rootfs and its
two tar helpers, the thin printer/Dockerfile, the `prebuilt` flag threaded
through both Replica implementations, and Replica.start's want_output, whose
only message was that the local build was about to be slow.

PRINTER_IMAGE is pinned to 1.9.7-1.2.9-20260810 rather than :latest. It is
now the entire substrate the brick-safety gates run on and the only input
nothing checksums, so a floating tag would let it change under a green suite
-- the drift the sha256 pins in both workflows exist to prevent.

THREE THINGS THAT COULD NOT HAVE PASSED, found while doing it:

  * Neither workflow built the feed. bin/patch.sh has refused to start
    without one since a1b4ea6, 45 commits after ci.yml was last touched.
    Both ran unpack/patch/pack straight into that guard.

  * `make release` ran bin/build.sh on $(RUN), which has no docker socket,
    while patch.sh assembles the payload inside the replica. `build` has
    used RUNBUILD all along; `release` was left behind. It also built no
    feed. It now builds one, once, outside the per-model loop -- nothing in
    it is model-specific.

  * ci.yml's shellcheck gate named pkgs/*/payload/init.d/S* and
    pkgs/*/prog/*.sh, neither of which exists any more; shellcheck exits 2
    on a path it cannot open. It is a `find` with an asserted count now,
    because the opposite failure is worse: a glob that quietly matches
    nothing checks nothing and still reports green.

Both workflows now go through `make` instead of hand-rolling `docker run`.
Hand-rolling meant CI exercised entry points no human uses, which is exactly
why the `release` runner bug could sit there unseen; it also ran as root and
left a work/ that the later `make release` could not write to.

ci.yml's test job builds the feed before the static lane. A good part of that
lane asks what is inside an .ipk and those questions do not fail without one
-- they return, and the lane reports a pass having never opened a package.
build-packages.sh needs no stock firmware, which is what makes that possible.

Docs, and the packages skill, which still documented pkg_buildopkg and
work/.opkg-host as how the payload is assembled -- the host opkg went in
dcd037c and the printer's own installs the feed now -- and still claimed
qa/static holds an ABI gate over every ELF in every package. It does not:
qa/replica/test_abi.py is the only one, and qa/static asserts a seventh does
not grow back.

Verified: qa/static is 122 passed / 110 errors here, identical to master --
every error is `vendor/opkg-utils is missing` in a checkout that has not run
`make vendor`. mkdocs build --strict passes. The new shellcheck gate was run
as written. The workflows themselves were not executed.

tools/replica/printer/*.sh live inside the published image, so those edits
take effect on the next `make printer-image`; behaviour is unchanged either
way, because nothing sets PROG_DUMP any more.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TrhjKabxDihvVjNQGGT4MK
2026-08-30 14:56:26 +03:00

36 lines
1.8 KiB
Bash

# creator5-custom-firmware -- TEST configuration
#
# cp test.env.example test.env
#
# Nothing in this file ever reaches a printer. It configures the replica --
# the printer's real rootfs under qemu-mipsel -- and nothing else. Build
# inputs and anything that ships live in config.env.
# ---- the replica image (REQUIRED) ------------------------------------------
# This is the replica. It carries the printer's rootfs, its real /usr/prog and
# /usr/data, AND the stock package already installed on top of them -- so the
# genuine klipper daemons, nginx, python3, checkEboard, moonraker and the
# printer's own OpenSSL 1.0.2d are all there, and package decryption is
# verified against the real implementation rather than a stand-in.
#
# There is no second way in. A local path used to exist -- `make rootfs`
# unsquashed rootfs.squashfs out of a stock package and a thin container
# mounted it, with PROG_DUMP pointing at the factory image for /usr/prog --
# and it cost ~60s of setup per test while needing the proprietary package on
# disk. The image needs neither, so it is the only source now.
#
# PINNED TO A VERSION, NOT :latest. This image is the entire substrate the
# brick-safety gates run on; a floating tag would let it change under a green
# suite, which is the same silent drift the sha256 pins in .github/workflows
# exist to prevent. Bump it deliberately when you rebuild.
#
# Built by tools/replica/build-printer-image.sh. It contains proprietary
# FlashForge firmware.
PRINTER_IMAGE="monstrofil/creator5-printer:1.9.7-1.2.9-20260810"
# Real partition sizes, as `df -h` reports them on the printer itself.
# Until these are set the replica's prog/data partitions are unbounded, so an
# install that runs the machine out of space would pass here and fail there.
PROG_MB=""
DATA_MB=""