Audit of the run-51 logs showed actions/cache@v3.3.2 works on the act_runner
(cold: "Cache saved" x4; next job: "Cache restored" in ~2s, npm --fast skip,
usign/dl reused) and the sdk-cache mirror seeds correctly — but the single
biggest recurring cost was NOT cached: `scripts/feeds update -a` re-cloned
base+packages+luci+routing+telephony every run (~7.8 min warm x 4 SDK jobs on
the serial runner ≈ ~28 min/run wasted; github ~1 MB/s from this host).
Cache .cache/feeds/{opkg,apk} (workspace dir, actions/cache-persisted, visible
in the SDK container via --volumes-from) symlinked over the SDK's empty feeds/:
`feeds update` now git-fetches deltas (seconds) instead of full clones, always
checking out feeds.conf's pins. Fail-safe: any error on the cached checkouts
wipes the cache and clones fresh. Key by SDK release (feeds-opkg-24.10.4 /
feeds-apk-25.12.1) — stable across runs, invalidates on an SDK bump; both arch
jobs of a lane share one entry (identical pins, serial runner).
Steady-state warm run: ~60+ min -> ~20-22 min. Also documented in the workflow
header: never key a cache on github.sha — each cache SAVE stalls the act_runner
~3 min, so per-run-changing keys would add +3 min/entry every run.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
117 lines
5.9 KiB
Bash
117 lines
5.9 KiB
Bash
#!/bin/sh
|
|
# Runs INSIDE an `openwrt/sdk:<target>-<ver>` container (CWD = SDK root
|
|
# /builder). The job's workspace is shared into this container via
|
|
# `docker run --volumes-from`, so the repo is visible at $REPO and output goes
|
|
# to $OUT (a dir under the repo, hence also visible to the runner afterwards).
|
|
#
|
|
# Unlike Shater v0.1 (which compiled ONLY xrayctl in the SDK and hand-packed the
|
|
# pure-data packages with tar), v0.2 builds ALL FOUR packages the canonical way,
|
|
# via the SDK feed + `make package/<p>/compile`:
|
|
#
|
|
# shaterd prebuilt binary — Build/Compile only VALIDATES that
|
|
# openwrt/shaterd/files/shaterd-<amd64|arm64>.upx was staged
|
|
# by scripts/build-shaterd.sh on the runner BEFORE this ran.
|
|
# (arch-specific .ipk: RSTRIP/STRIP disabled — packed ELF.)
|
|
# shater-core PKGARCH=all data glue (procd init, sysctl, uci-defaults).
|
|
# luci-app-shater PKGARCH=all LuCI thin launcher — its Makefile does
|
|
# `include $(TOPDIR)/feeds/luci/luci.mk`, so the `luci` feed
|
|
# MUST be updated first (that is what creates feeds/luci/luci.mk).
|
|
# byedpi arch-specific C — the SDK cross-compiles ciadpi from the
|
|
# upstream tarball (needs network for PKG_SOURCE_URL).
|
|
#
|
|
# Env (required): ARCH, REPO, OUT.
|
|
set -eu
|
|
ARCH="${ARCH:?ARCH env required}"
|
|
REPO="${REPO:?REPO env required}"
|
|
OUT="${OUT:?OUT env required}"
|
|
mkdir -p "$OUT"
|
|
|
|
echo "[sdk] arch=$ARCH repo=$REPO out=$OUT"
|
|
test -f "$REPO/openwrt/shaterd/Makefile" || {
|
|
echo "[sdk] ERROR: feed not mounted ($REPO/openwrt/shaterd/Makefile missing)"; ls -la "$REPO" || true; exit 9; }
|
|
|
|
# The prebuilt shaterd artifact must already be staged for this arch.
|
|
case "$ARCH" in
|
|
x86_64) sfx=amd64 ;;
|
|
aarch64_cortex-a53) sfx=arm64 ;;
|
|
*) echo "[sdk] ERROR: unsupported ARCH '$ARCH'"; exit 2 ;;
|
|
esac
|
|
test -f "$REPO/openwrt/shaterd/files/shaterd-$sfx.upx" || {
|
|
echo "[sdk] ERROR: openwrt/shaterd/files/shaterd-$sfx.upx not staged."
|
|
echo " scripts/build-shaterd.sh must run on the runner before the SDK build."; exit 3; }
|
|
|
|
# --- register this repo's openwrt/ as a src-link feed named `shater` ---------
|
|
# src-link REQUIRES an absolute path; $REPO/openwrt is exactly a feed root (it
|
|
# contains the 4 package dirs and nothing else that looks like a package).
|
|
cp -f feeds.conf.default feeds.conf
|
|
grep -q '^src-link shater ' feeds.conf || echo "src-link shater $REPO/openwrt" >> feeds.conf
|
|
|
|
# Update metadata for ALL feeds: our `shater` feed + the SDK defaults (base,
|
|
# luci, packages, routing, telephony). We need `luci` for feeds/luci/luci.mk and
|
|
# `base`/`packages` for the runtime deps (kmod-nft-tproxy, kmod-nft-socket,
|
|
# ip-full, rpcd, luci-base) to resolve.
|
|
#
|
|
# Persistent feeds checkouts: $FEEDS_CACHE (a workspace dir the runner restores
|
|
# via actions/cache, shared into this container via --volumes-from) replaces
|
|
# the SDK's ephemeral feeds/ dir, so `feeds update` git-fetches deltas instead
|
|
# of re-cloning base+packages+luci every run (~7 min on the runner's slow
|
|
# github.com link). Correctness-safe: update always checks out feeds.conf's
|
|
# pinned revisions; if it ever fails on a cached checkout (e.g. a force-pushed
|
|
# upstream), the cache is wiped and the update retried with fresh clones.
|
|
if [ -n "${FEEDS_CACHE:-}" ] && mkdir -p "$FEEDS_CACHE" 2>/dev/null; then
|
|
rm -rf feeds
|
|
ln -s "$FEEDS_CACHE" feeds
|
|
echo "[sdk] feeds/ -> $FEEDS_CACHE (persistent cache)"
|
|
fi
|
|
echo "[sdk] feeds update -a"
|
|
if ! ./scripts/feeds update -a; then
|
|
[ -L feeds ] || { echo "[sdk] ERROR: feeds update failed"; exit 8; }
|
|
echo "[sdk] WARNING: feeds update failed on cached checkouts — wiping cache, cloning fresh"
|
|
find "$FEEDS_CACHE" -mindepth 1 -maxdepth 1 -exec rm -rf {} + 2>/dev/null || true
|
|
./scripts/feeds update -a
|
|
fi
|
|
|
|
echo "[sdk] feeds install (prefer shater feed)"
|
|
./scripts/feeds install -p shater shaterd shater-core byedpi luci-app-shater
|
|
|
|
# Select our packages, then defconfig. `make package/<p>/compile` builds the
|
|
# explicit target regardless, but selecting first makes deps visible to defconfig.
|
|
for p in shaterd shater-core byedpi luci-app-shater; do
|
|
echo "CONFIG_PACKAGE_$p=m" >> .config
|
|
done
|
|
# Route source downloads through OpenWrt's fast CDN mirror FIRST — sourceware.org
|
|
# (elfutils) and other upstreams intermittently stall mid-transfer, and curl's
|
|
# --connect-timeout doesn't cover a stalled stream, so the SDK download hangs the
|
|
# build. LOCALMIRROR is tried before each package's own PKG_SOURCE_URL. (lx CI)
|
|
echo 'CONFIG_LOCALMIRROR="https://sources.cdn.openwrt.org"' >> .config
|
|
# Persistent dl/ across runs: $DL_DIR is a workspace dir the runner restores via
|
|
# actions/cache (see ci/build-feed.sh). Correctness-safe: the buildroot verifies
|
|
# PKG_HASH on every file already in dl/ and re-downloads on mismatch, so a stale
|
|
# cache can never leak a wrong source into the build.
|
|
if [ -n "${DL_DIR:-}" ]; then
|
|
echo "CONFIG_DOWNLOAD_FOLDER=\"$DL_DIR\"" >> .config
|
|
fi
|
|
echo "[sdk] defconfig"
|
|
make defconfig >/dev/null
|
|
|
|
# --- compile the 4 packages --------------------------------------------------
|
|
for p in shaterd shater-core byedpi luci-app-shater; do
|
|
echo "[sdk] === build $p ==="
|
|
make "package/$p/compile" V=s -j"$(nproc)"
|
|
done
|
|
|
|
# --- collect ONLY our 4 packages' .ipk (per-arch shaterd/byedpi + _all core/luci)
|
|
# NOT `find bin -name '*.ipk'`: the openwrt/sdk image ships HUNDREDS of prebuilt
|
|
# kmod/base .ipk under bin/, which a blanket copy would pull into the feed and
|
|
# get signed under OUR key. Match each package's own `<name>_<ver>_<arch>.ipk`.
|
|
found=0
|
|
for p in shaterd shater-core byedpi luci-app-shater; do
|
|
for ipk in $(find bin -type f -name "${p}_*.ipk"); do
|
|
cp -f "$ipk" "$OUT/"; found=$((found+1))
|
|
done
|
|
done
|
|
[ "$found" -ge 4 ] || { echo "[sdk] ERROR: expected >=4 of OUR .ipk, collected $found"; echo "[sdk] (all .ipk under bin/:)"; find bin -type f -name '*.ipk' | head -20; exit 4; }
|
|
chmod -R a+rwX "$OUT" 2>/dev/null || true
|
|
echo "[sdk] OK arch=$ARCH — collected $found of our .ipk:"
|
|
ls -l "$OUT"
|