Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bca821d3e | ||
|
|
3648e37a1e | ||
|
|
d109e08fab |
2
bible
2
bible
Submodule bible updated: 98448c993f...d2600f1279
31
bible-local/rules/patterns/ascii-safe-text/contract.md
Normal file
31
bible-local/rules/patterns/ascii-safe-text/contract.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Contract: ASCII-Safe Text in Scripts and Boot Configs
|
||||||
|
|
||||||
|
Version: 1.0
|
||||||
|
|
||||||
|
## Principle
|
||||||
|
|
||||||
|
Shell scripts, bootloader configs, and any text rendered on serial/SOL consoles must use only printable ASCII characters. Non-ASCII Unicode — including typographic punctuation such as the em-dash (U+2014 `—`), en-dash (U+2013 `–`), curly quotes, and ellipsis (U+2026 `…`) — breaks rendering on serial terminals, GRUB text/serial mode, IPMI SOL, and tooling that assumes ASCII.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- Never use em-dash (`—`) or en-dash (`–`) in any shell script, GRUB config, syslinux/isolinux config, or service unit file. Use ASCII double-hyphen `--` or single hyphen `-` instead.
|
||||||
|
- Never use curly quotes (`"` `"` `'` `'`) in shell scripts or configs. Use straight quotes `"` and `'`.
|
||||||
|
- Never use the Unicode ellipsis (`…`). Use `...`.
|
||||||
|
- GRUB `menuentry` and `submenu` titles must be ASCII-only — GRUB serial terminal output is ASCII; non-ASCII characters render as garbage or are dropped.
|
||||||
|
- Comments in GRUB theme files (`.txt`) must also be ASCII-only, as GRUB may parse the entire file.
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
GRUB renders menus over both `gfxterm` (graphical, Unicode-capable) and `serial` (ASCII-only) simultaneously when `terminal_output gfxterm serial` is set. The serial output — used by IPMI SOL and BMC remote consoles — cannot display multi-byte UTF-8 sequences and shows raw bytes or drops characters. A menuentry title `"EASY-BEE — GSP=off"` appears as `"EASY-BEE â€" GSP=off"` or `"EASY-BEE GSP=off"` on SOL, making the menu unreadable.
|
||||||
|
|
||||||
|
## Anti-patterns
|
||||||
|
|
||||||
|
- `menuentry "EASY-BEE — GSP=off"` — em-dash in GRUB title
|
||||||
|
- `# bee logo — centered` — em-dash in GRUB theme comment
|
||||||
|
- `echo "done — reboot"` in a shell script displayed over serial
|
||||||
|
|
||||||
|
## Correct form
|
||||||
|
|
||||||
|
- `menuentry "EASY-BEE -- GSP=off"`
|
||||||
|
- `# bee logo - centered`
|
||||||
|
- `echo "done - reboot"`
|
||||||
@@ -31,10 +31,10 @@ Build with explicit SSH keys baked into the ISO:
|
|||||||
sh iso/builder/build-in-container.sh --authorized-keys ~/.ssh/id_ed25519.pub
|
sh iso/builder/build-in-container.sh --authorized-keys ~/.ssh/id_ed25519.pub
|
||||||
```
|
```
|
||||||
|
|
||||||
Rebuild the builder image:
|
Force a clean rebuild of the builder image and build caches:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sh iso/builder/build-in-container.sh --rebuild-image
|
sh iso/builder/build-in-container.sh --clean-build
|
||||||
```
|
```
|
||||||
|
|
||||||
Use a custom cache directory:
|
Use a custom cache directory:
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ IMAGE_TAG="${BEE_BUILDER_IMAGE:-bee-iso-builder}"
|
|||||||
BUILDER_PLATFORM="${BEE_BUILDER_PLATFORM:-linux/amd64}"
|
BUILDER_PLATFORM="${BEE_BUILDER_PLATFORM:-linux/amd64}"
|
||||||
CACHE_DIR="${BEE_BUILDER_CACHE_DIR:-${REPO_ROOT}/dist/container-cache}"
|
CACHE_DIR="${BEE_BUILDER_CACHE_DIR:-${REPO_ROOT}/dist/container-cache}"
|
||||||
AUTH_KEYS=""
|
AUTH_KEYS=""
|
||||||
REBUILD_IMAGE=0
|
|
||||||
CLEAN_CACHE=0
|
CLEAN_CACHE=0
|
||||||
VARIANT="all"
|
VARIANT="all"
|
||||||
|
|
||||||
@@ -22,17 +21,12 @@ while [ $# -gt 0 ]; do
|
|||||||
CACHE_DIR="$2"
|
CACHE_DIR="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
--rebuild-image)
|
|
||||||
REBUILD_IMAGE=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--authorized-keys)
|
--authorized-keys)
|
||||||
AUTH_KEYS="$2"
|
AUTH_KEYS="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
--clean-build)
|
--clean-build)
|
||||||
CLEAN_CACHE=1
|
CLEAN_CACHE=1
|
||||||
REBUILD_IMAGE=1
|
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--variant)
|
--variant)
|
||||||
@@ -41,7 +35,7 @@ while [ $# -gt 0 ]; do
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "unknown arg: $1" >&2
|
echo "unknown arg: $1" >&2
|
||||||
echo "usage: $0 [--cache-dir /path] [--rebuild-image] [--clean-build] [--authorized-keys /path/to/authorized_keys] [--variant nvidia|nvidia-legacy|amd|nogpu|all]" >&2
|
echo "usage: $0 [--cache-dir /path] [--clean-build] [--authorized-keys /path/to/authorized_keys] [--variant nvidia|nvidia-legacy|amd|nogpu|all]" >&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -105,7 +99,7 @@ image_matches_platform() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NEED_BUILD_IMAGE=0
|
NEED_BUILD_IMAGE=0
|
||||||
if [ "$REBUILD_IMAGE" = "1" ]; then
|
if [ "$CLEAN_CACHE" = "1" ]; then
|
||||||
NEED_BUILD_IMAGE=1
|
NEED_BUILD_IMAGE=1
|
||||||
elif ! "$CONTAINER_TOOL" image inspect "${IMAGE_REF}" >/dev/null 2>&1; then
|
elif ! "$CONTAINER_TOOL" image inspect "${IMAGE_REF}" >/dev/null 2>&1; then
|
||||||
NEED_BUILD_IMAGE=1
|
NEED_BUILD_IMAGE=1
|
||||||
|
|||||||
@@ -848,6 +848,72 @@ reset_live_build_stage() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Marker written after every successful full lb build for this variant
|
||||||
|
FULL_BUILD_MARKER="${BUILD_WORK_DIR}/.bee-full-build-marker"
|
||||||
|
|
||||||
|
# Returns 0 if full lb build is needed, 1 if fast-path is safe.
|
||||||
|
# Fast-path is safe when only light files changed since the last full build
|
||||||
|
# (Go source, overlay scripts/configs). Heavy changes (VERSIONS, package lists,
|
||||||
|
# hooks, archives, Dockerfile, auto/config) require a full lb build.
|
||||||
|
needs_full_build() {
|
||||||
|
[ -f "${FULL_BUILD_MARKER}" ] || return 0
|
||||||
|
[ -f "${BUILD_WORK_DIR}/binary/live/filesystem.squashfs" ] || return 0
|
||||||
|
[ -f "${BUILD_WORK_DIR}/live-image-amd64.hybrid.iso" ] || return 0
|
||||||
|
|
||||||
|
_heavy=$(find \
|
||||||
|
"${BUILDER_DIR}/VERSIONS" \
|
||||||
|
"${BUILDER_DIR}/auto/config" \
|
||||||
|
"${BUILDER_DIR}/Dockerfile" \
|
||||||
|
"${BUILDER_DIR}/config/package-lists" \
|
||||||
|
"${BUILDER_DIR}/config/hooks" \
|
||||||
|
"${BUILDER_DIR}/config/archives" \
|
||||||
|
-newer "${FULL_BUILD_MARKER}" 2>/dev/null | head -1)
|
||||||
|
|
||||||
|
if [ -n "$_heavy" ]; then
|
||||||
|
echo "=== full build required: heavy config changed: $(basename "$_heavy") ==="
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fast-path: unsquash existing filesystem, rsync overlay on top, repack.
|
||||||
|
# Requires ~10 GB free in BEE_CACHE_DIR for the unpacked squashfs.
|
||||||
|
fast_path_repack_squashfs() {
|
||||||
|
_sq="${BUILD_WORK_DIR}/binary/live/filesystem.squashfs"
|
||||||
|
_tmp="${BEE_CACHE_DIR}/fast-unsquash-${BUILD_VARIANT}"
|
||||||
|
echo "=== fast-path: unsquash ($(du -sh "$_sq" | cut -f1) compressed) ==="
|
||||||
|
rm -rf "$_tmp"
|
||||||
|
unsquashfs -d "$_tmp" "$_sq"
|
||||||
|
echo "=== fast-path: syncing overlay stage ==="
|
||||||
|
rsync -a --checksum "${OVERLAY_STAGE_DIR}/" "$_tmp/"
|
||||||
|
echo "=== fast-path: repacking squashfs ==="
|
||||||
|
_sq_new="${_sq}.new"
|
||||||
|
rm -f "$_sq_new"
|
||||||
|
mksquashfs "$_tmp" "$_sq_new" -comp zstd -b 1048576 -noappend -no-progress
|
||||||
|
mv "$_sq_new" "$_sq"
|
||||||
|
rm -rf "$_tmp"
|
||||||
|
echo "=== fast-path: squashfs repacked ($(du -sh "$_sq" | cut -f1)) ==="
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fast-path: rebuild ISO by replacing only live/filesystem.squashfs via xorriso.
|
||||||
|
# Boot structure (El Torito, EFI, MBR hybrid) is replayed from the prior ISO.
|
||||||
|
fast_path_rebuild_iso() {
|
||||||
|
_sq="${BUILD_WORK_DIR}/binary/live/filesystem.squashfs"
|
||||||
|
_prior="${BUILD_WORK_DIR}/live-image-amd64.hybrid.iso"
|
||||||
|
_new="${BUILD_WORK_DIR}/live-image-amd64.hybrid.iso.new"
|
||||||
|
echo "=== fast-path: rebuilding ISO with xorriso ==="
|
||||||
|
rm -f "$_new"
|
||||||
|
xorriso \
|
||||||
|
-indev "$_prior" \
|
||||||
|
-outdev "$_new" \
|
||||||
|
-map "$_sq" /live/filesystem.squashfs \
|
||||||
|
-boot_image any replay \
|
||||||
|
-commit
|
||||||
|
mv "$_new" "$_prior"
|
||||||
|
echo "=== fast-path: ISO rebuilt ==="
|
||||||
|
}
|
||||||
|
|
||||||
recover_iso_memtest() {
|
recover_iso_memtest() {
|
||||||
lb_dir="$1"
|
lb_dir="$1"
|
||||||
iso_path="$2"
|
iso_path="$2"
|
||||||
@@ -1487,6 +1553,21 @@ if [ -f "${LB_INCLUDES}/root/.ssh/authorized_keys" ]; then
|
|||||||
chmod 600 "${LB_INCLUDES}/root/.ssh/authorized_keys"
|
chmod 600 "${LB_INCLUDES}/root/.ssh/authorized_keys"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- auto fast-path: squashfs surgery if only light files changed ---
|
||||||
|
if ! needs_full_build; then
|
||||||
|
echo "=== fast-path build (no heavy config changes since last full build) ==="
|
||||||
|
fast_path_repack_squashfs
|
||||||
|
fast_path_rebuild_iso
|
||||||
|
ISO_RAW="${LB_DIR}/live-image-amd64.hybrid.iso"
|
||||||
|
validate_iso_live_boot_entries "$ISO_RAW"
|
||||||
|
validate_iso_nvidia_runtime "$ISO_RAW"
|
||||||
|
cp "$ISO_RAW" "$ISO_OUT"
|
||||||
|
echo ""
|
||||||
|
echo "=== done (${BUILD_VARIANT}, fast-path) ==="
|
||||||
|
echo "ISO: $ISO_OUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
# --- build ISO using live-build ---
|
# --- build ISO using live-build ---
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== building ISO (variant: ${BUILD_VARIANT}) ==="
|
echo "=== building ISO (variant: ${BUILD_VARIANT}) ==="
|
||||||
@@ -1535,6 +1616,7 @@ if [ -f "$ISO_RAW" ]; then
|
|||||||
validate_iso_live_boot_entries "$ISO_RAW"
|
validate_iso_live_boot_entries "$ISO_RAW"
|
||||||
validate_iso_nvidia_runtime "$ISO_RAW"
|
validate_iso_nvidia_runtime "$ISO_RAW"
|
||||||
cp "$ISO_RAW" "$ISO_OUT"
|
cp "$ISO_RAW" "$ISO_OUT"
|
||||||
|
touch "${FULL_BUILD_MARKER}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== done (${BUILD_VARIANT}) ==="
|
echo "=== done (${BUILD_VARIANT}) ==="
|
||||||
echo "ISO: $ISO_OUT"
|
echo "ISO: $ISO_OUT"
|
||||||
|
|||||||
Reference in New Issue
Block a user