Both routers are past opkg: mini_router runs ImmortalWrt 25.12.1 and main_router OpenWrt 25.12.0, both with apk-tools 3.0.5, and main_router has no `opkg` binary at all. The 24.10 lane was building and signing a feed no device could consume. Removed jobs `build` and `release` with the scripts only they called (ci/build-feed.sh, ci/sdk-build.sh, ci/make-index.sh, ci/install-usign.sh) and the usign trust anchor dist/shater-feed.pub. A committed public key is an instruction: it invites the old install path for a feed that is no longer produced. The key is retired, not revoked -- git history keeps it, KEY_BUILD still holds the secret half, and a usign secret contains its own public half, so the identity is reconstructible if a 24.10 device ever needs serving. D7 is marked SUPERSEDED by the new D22 rather than deleted. Separately: the rolling `apk-latest-<arch>` release was frozen at 0.2.0 from 2026-07-24 while every tag run published its versioned release correctly. The publish loop was an either/or -- `TAG=apk-latest-<arch>` when VER=latest (workflow_dispatch only), ELSE `TAG=apk-<ver>-<arch>` -- so a `v*` tag run never touched the rolling pointer. Asset replacement was never the problem; ci/gitea-release.sh already deletes before recreating. A router pinned to the rolling URL sat on 0.2.0 while `apk update` reported success: silent staleness, the failure mode this repo keeps having to close. The rolling pointer is now published on EVERY run, tag runs included, and a new assert reads the release back over the API afterwards: our three tag-versioned packages at the built version plus the index and the key must be present (exit 13), and no package asset at any other version may survive (exit 14). Same class of check as sdk-build-apk.sh's package-version assert, added for the same reason -- the previous failure mode was silent. KEY_BUILD can now be deleted from the Gitea repo secrets; nothing references it. Docs state plainly that mini_router is deliberately pinned to a versioned URL and that the hand-edit per release is the price of pinning. Known consequence: the x86_64 QEMU testbed is still OpenWrt 24.10.3 and can no longer install our packages. Its 25.12 rebuild is in flight separately. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4PcWfrBRyg4eWN58axaGN
126 lines
5.8 KiB
Makefile
126 lines
5.8 KiB
Makefile
#
|
|
# shaterd — the single Shater v0.2 Go daemon (PREBUILT binary package).
|
|
#
|
|
# `shaterd` embeds the sing-box engine (box.New, in-process), the control-plane,
|
|
# the in-process DNS filter, the stats aggregator AND the admin-panel SPA
|
|
# (//go:embed all:webroot). shater-core's procd init supervises `shaterd run`;
|
|
# shater-core DEPENDS:=+shaterd, so THIS package is what resolves that dep.
|
|
#
|
|
# WHY PREBUILT (not from-source in the SDK)
|
|
# -----------------------------------------
|
|
# The shipped binary is the product of a toolchain the OpenWrt SDK cannot easily
|
|
# reproduce:
|
|
# * a Vite/npm build of the React SPA (Node is not guaranteed in an SDK env),
|
|
# * that SPA embedded via //go:embed all:webroot at `go build` time,
|
|
# * the D9 musl-static router tag set (CGO_ENABLED=0, fully static ET_EXEC),
|
|
# * a UPX --lzma --best pass (D10) that takes ~42 MB → ~10 MB.
|
|
# Reproducing npm + embed + UPX inside the SDK is fragile; instead we build the
|
|
# binary out-of-tree with scripts/build-shaterd.sh (host or CI) and package the
|
|
# arch-matched artifact. This mirrors the common Go+asset+UPX prebuilt pattern.
|
|
#
|
|
# HOW CI STAGES THE BINARY
|
|
# ------------------------
|
|
# scripts/build-shaterd.sh copies its output into this package's files/ dir:
|
|
# dist/shaterd-<a>.upx -> openwrt/shaterd/files/shaterd-<a>.upx (a ∈ amd64,arm64)
|
|
# The SDK build then picks files/shaterd-$(ARCH-mapped).upx below. So CI order is:
|
|
# 1) scripts/build-shaterd.sh (produces + stages both arches)
|
|
# 2) copy openwrt/* into the SDK feed, `make package/shaterd/compile`
|
|
# The staged binaries are gitignored (they are release artifacts, not source).
|
|
#
|
|
# The binary is a fully static musl-safe ELF, so DEPENDS is empty (no libc/shared
|
|
# deps). The data-plane kmods + ip-full live on shater-core.
|
|
#
|
|
|
|
include $(TOPDIR)/rules.mk
|
|
|
|
PKG_NAME:=shaterd
|
|
|
|
# VERSIONING — derived from the git tag, NOT hand-maintained here (bug B4).
|
|
# ci/version.sh turns `git describe` into SHATER_PKG_VERSION/SHATER_PKG_RELEASE
|
|
# (tag vX.Y.Z -> X.Y.Z + r1; off-tag -> last tag + r<commits+1>), and
|
|
# ci/build-feed-apk.sh exports them into the SDK build env. ci/sdk-build-apk.sh
|
|
# then ASSERTS that the produced .apk really carries that version, so a lost env
|
|
# can never silently ship a stale one again.
|
|
# The literals below are ONLY the manual/offline fallback (no CI, no git) — they
|
|
# are not "the release version"; releases are named by the tag.
|
|
PKG_VERSION:=$(if $(SHATER_PKG_VERSION),$(SHATER_PKG_VERSION),0.2.0)
|
|
PKG_RELEASE:=$(if $(SHATER_PKG_RELEASE),$(SHATER_PKG_RELEASE),1)
|
|
|
|
PKG_MAINTAINER:=Shater <maqrota@icloud.com>
|
|
PKG_LICENSE:=GPL-3.0-or-later
|
|
|
|
include $(INCLUDE_DIR)/package.mk
|
|
|
|
# Map the OpenWrt target $(ARCH) to the scripts/build-shaterd.sh artifact suffix.
|
|
# Extend BOTH this map and ARCHES in build-shaterd.sh to publish more router arches.
|
|
# x86_64 -> amd64 (x86 routers / the test VM)
|
|
# aarch64 -> arm64 (both BPI routers are aarch64_cortex-a53)
|
|
SHATERD_ARTIFACT:=$(strip \
|
|
$(if $(filter x86_64,$(ARCH)),amd64,\
|
|
$(if $(filter aarch64,$(ARCH)),arm64,)))
|
|
|
|
SHATERD_BIN:=shaterd-$(SHATERD_ARTIFACT).upx
|
|
|
|
# The staged binary is already UPX-compressed; the SDK's default RSTRIP pass would
|
|
# corrupt a packed executable, so disable stripping for this package (no-op `:`).
|
|
RSTRIP:=:
|
|
STRIP:=:
|
|
|
|
define Package/shaterd
|
|
SECTION:=net
|
|
CATEGORY:=Network
|
|
TITLE:=Shater v0.2 daemon (prebuilt static musl, SPA-embedded, UPX)
|
|
URL:=https://github.com/shater
|
|
# Static musl ELF (CGO_ENABLED=0): no shared-lib deps beyond the kernel.
|
|
DEPENDS:=
|
|
endef
|
|
|
|
define Package/shaterd/description
|
|
The single Shater v0.2 daemon. One long-lived Go process that embeds the
|
|
sing-box engine (in-process, box.New), the control-plane, the in-process DNS
|
|
filter, the statistics aggregator and the embedded Faceplate admin-panel SPA.
|
|
Supervised by shater-core's procd init as `shaterd run`. This package ships a
|
|
prebuilt, statically-linked (musl-safe), UPX-compressed binary produced out of
|
|
tree by scripts/build-shaterd.sh (npm SPA build + //go:embed + D9 tags + D10 UPX).
|
|
endef
|
|
|
|
# Nothing to fetch. Build/Compile only VALIDATES that the arch-matched prebuilt
|
|
# artifact was staged (scripts/build-shaterd.sh) before the SDK build.
|
|
define Build/Prepare
|
|
mkdir -p $(PKG_BUILD_DIR)
|
|
endef
|
|
|
|
define Build/Compile
|
|
$(if $(SHATERD_ARTIFACT),,$(error shaterd: no prebuilt artifact mapped for OpenWrt ARCH '$(ARCH)'. Add it to scripts/build-shaterd.sh (ARCHES) and the ARCH map in openwrt/shaterd/Makefile))
|
|
@test -f $(CURDIR)/files/$(SHATERD_BIN) || { \
|
|
echo "shaterd: staged binary files/$(SHATERD_BIN) not found."; \
|
|
echo " Run scripts/build-shaterd.sh first — it stages dist/shaterd-$(SHATERD_ARTIFACT).upx"; \
|
|
echo " into openwrt/shaterd/files/$(SHATERD_BIN) for ARCH=$(ARCH)."; \
|
|
exit 1; }
|
|
endef
|
|
|
|
define Package/shaterd/install
|
|
$(INSTALL_DIR) $(1)/usr/bin
|
|
$(INSTALL_BIN) $(CURDIR)/files/$(SHATERD_BIN) $(1)/usr/bin/shaterd
|
|
endef
|
|
|
|
# This package ships ONLY the binary — no init script — so the package manager's
|
|
# postinst never touches the running service. On `apk upgrade shaterd` the new
|
|
# ELF lands at /usr/bin/shaterd while the OLD image keeps running from its
|
|
# unlinked inode: the upgrade silently has no effect until the next reboot, and
|
|
# meanwhile the new CLI (`shaterd reconcile`, `status`, `mint-token` — invoked by
|
|
# cron/hotplug/rpcd) talks over the control socket to an old daemon. Restart the
|
|
# service here, but ONLY if it was actually running, so a first install (where
|
|
# shater-core may not be unpacked yet) and offline image builds stay untouched.
|
|
define Package/shaterd/postinst
|
|
#!/bin/sh
|
|
[ -n "$${IPKG_INSTROOT}" ] && exit 0
|
|
if [ -x /etc/init.d/shater ] && pidof shaterd >/dev/null 2>&1; then
|
|
logger -t shaterd -p daemon.notice "binary upgraded — restarting the shater service"
|
|
/etc/init.d/shater restart >/dev/null 2>&1
|
|
fi
|
|
exit 0
|
|
endef
|
|
|
|
$(eval $(call BuildPackage,shaterd))
|