From 96d14513e8f9a51a0c218ed37a0b78d854e18c17 Mon Sep 17 00:00:00 2001 From: gnacho Date: Fri, 18 Sep 2026 23:13:35 +0200 Subject: [PATCH] feat(ci): add armv7 (ipq40xx) build target with self-update, heal and installer support (#325) --- .github/workflows/openwrt-package.yml | 38 +++++++++++++++++-- README.es.md | 5 ++- README.md | 5 ++- .../files/usr/libexec/netgrip-heal-register | 11 +++--- install.sh | 6 ++- internal/modules/selfupdate.go | 4 ++ 6 files changed, 55 insertions(+), 14 deletions(-) diff --git a/.github/workflows/openwrt-package.yml b/.github/workflows/openwrt-package.yml index e108c001..4f4be51d 100644 --- a/.github/workflows/openwrt-package.yml +++ b/.github/workflows/openwrt-package.yml @@ -91,6 +91,20 @@ jobs: goarch: mipsle pkgarch: mipsel_24kc upload-binary: true + - sdk-version: 24.10.5 + sdk-target: ipq40xx/generic + format: ipk + arch: armv7 + goarch: arm + pkgarch: arm_cortex-a7_neon-vfpv4 + upload-binary: true + - sdk-version: 25.12.5 + sdk-target: ipq40xx/generic + format: apk + arch: armv7 + goarch: arm + pkgarch: arm_cortex-a7_neon-vfpv4 + upload-binary: false steps: - uses: actions/checkout@v4 @@ -122,7 +136,14 @@ jobs: env: TAG: ${{ steps.tag.outputs.tag }} run: | - GOOS=linux GOARCH=${{ matrix.goarch }} GOMIPS=softfloat CGO_ENABLED=0 go build \ + # armv7 (ipq40xx) needs GOARM=7; mips needs soft-float. Other arches + # ignore both (GOMIPS only affects mips, GOARM only arm). + if [ "${{ matrix.goarch }}" = "arm" ]; then + export GOARM=7 + else + export GOMIPS=softfloat + fi + GOOS=linux GOARCH=${{ matrix.goarch }} CGO_ENABLED=0 go build \ -ldflags "-s -w -X main.version=${TAG}" -o /tmp/netgrip ./cmd/netgrip ls -la /tmp/netgrip file /tmp/netgrip @@ -191,6 +212,14 @@ jobs: sdk-target: x86/64 format: apk arch: amd64 + - sdk-version: 24.10.5 + sdk-target: ipq40xx/generic + format: ipk + arch: armv7 + - sdk-version: 25.12.5 + sdk-target: ipq40xx/generic + format: apk + arch: armv7 steps: - uses: actions/checkout@v4 @@ -226,10 +255,11 @@ jobs: run: | echo "LuCI packages generated:" ls -la dist/packages/ - # The luci-app ipk is arch-all: both 24.10 legs would upload the + # The luci-app ipk is arch-all: every 24.10 leg would upload the # same filename concurrently and race on the release assets. - # Upload it once, from the arm64 leg (#214). - if [ "${{ matrix.format }}" = "ipk" ] && [ "${{ matrix.arch }}" = "amd64" ]; then + # Upload it once, from the arm64 leg (#214); the other ipk legs + # (x86_64, mipsel, armv7) skip. + if [ "${{ matrix.format }}" = "ipk" ] && [ "${{ matrix.arch }}" != "arm64" ]; then echo "luci ipk is arch-all; already uploaded by the arm64 leg, skipping." exit 0 fi diff --git a/README.es.md b/README.es.md index 7bc67623..b77f4f85 100644 --- a/README.es.md +++ b/README.es.md @@ -115,8 +115,9 @@ capacidad adicional, no un requisito: si no usas NetPulse, nada cambia. ## Ponlo en tu router -Requisitos: un router ARM de 64 bits (`aarch64_cortex-a53`, cubre MediaTek -filogic y Qualcomm ipq807x) o x86_64, con OpenWrt 24.10 o 25.12. El panel +Requisitos: un router ARM (`aarch64_cortex-a53`, cubre MediaTek +filogic y Qualcomm ipq807x; u `arm_cortex-a7_neon-vfpv4`, cubre +Qualcomm ipq40xx) o x86_64, con OpenWrt 24.10 o 25.12. El panel escucha en el puerto 8090 y entra con tus credenciales de LuCI. SSH al router y ejecuta: diff --git a/README.md b/README.md index 8e25e1b8..9f6857cf 100644 --- a/README.md +++ b/README.md @@ -112,8 +112,9 @@ a capability, not a requirement: if you do not use NetPulse, nothing changes. ## Get it on your router -Requirements: a 64-bit ARM router (`aarch64_cortex-a53`, covers MediaTek -filogic and Qualcomm ipq807x) or x86_64, running OpenWrt 24.10 or 25.12. The +Requirements: an ARM router (`aarch64_cortex-a53`, covers MediaTek +filogic and Qualcomm ipq807x; or `arm_cortex-a7_neon-vfpv4`, covers +Qualcomm ipq40xx) or x86_64, running OpenWrt 24.10 or 25.12. The panel listens on port 8090 and logs in with your LuCI credentials. SSH into the router and run: diff --git a/deploy/openwrt/netgrip/files/usr/libexec/netgrip-heal-register b/deploy/openwrt/netgrip/files/usr/libexec/netgrip-heal-register index fea68fdd..764237f1 100755 --- a/deploy/openwrt/netgrip/files/usr/libexec/netgrip-heal-register +++ b/deploy/openwrt/netgrip/files/usr/libexec/netgrip-heal-register @@ -49,8 +49,9 @@ log "registry entry lost (running ${ver:-unknown}): restoring" if command -v apk >/dev/null 2>&1; then arch=$(apk --print-arch 2>/dev/null) case "$arch" in - aarch64*) asset=netgrip-*-arm64.apk ;; - x86_64*) asset=netgrip-*-amd64.apk ;; + aarch64*) pattern='netgrip-[^/]*-arm64\.apk$' ;; + x86_64*) pattern='netgrip-[^/]*-amd64\.apk$' ;; + arm_cortex-a7*) pattern='netgrip-[^/]*-armv7\.apk$' ;; *) log "no release asset for apk arch $arch"; exit 1 ;; esac pkgfile=/tmp/netgrip-heal.apk @@ -62,7 +63,7 @@ else arch=$(opkg print-architecture 2>/dev/null | awk 'tolower($1)=="arch" && $2!="all" && $2!="noarch" {print $2; exit}') fi [ -n "$arch" ] || { log "cannot determine architecture"; exit 1; } - asset="netgrip*_${arch}.ipk" + pattern="netgrip_[^/]*_${arch}\.ipk$" pkgfile=/tmp/netgrip-heal.ipk fi @@ -79,8 +80,8 @@ done json=$(wget -q -O - -T 15 "$RELEASES_API" 2>/dev/null) [ -n "$json" ] || { log "cannot reach GitHub releases API"; exit 1; } -url=$(printf '%s' "$json" | tr ',' '\n' | grep -o '"browser_download_url": *"[^"]*"' | cut -d'"' -f4 | grep -E "/netgrip_[^/]*_${arch}\.ipk$" | head -n1) -[ -n "$url" ] || { log "no release asset matching $asset"; exit 1; } +url=$(printf '%s' "$json" | tr ',' '\n' | grep -o '"browser_download_url": *"[^"]*"' | cut -d'"' -f4 | grep -E "/${pattern}" | head -n1) +[ -n "$url" ] || { log "no release asset matching ${pattern}"; exit 1; } # Never downgrade a dev build: only heal when the asset matches the # running version. diff --git a/install.sh b/install.sh index c44320eb..e4fe05af 100755 --- a/install.sh +++ b/install.sh @@ -35,8 +35,12 @@ case "$(uname -m)" in ASSET_ARCH=amd64 IPK_ARCH=x86_64 ;; + armv7l|armv7) + ASSET_ARCH=armv7 + IPK_ARCH=arm_cortex-a7_neon-vfpv4 + ;; *) - die 3 "unsupported architecture: $(uname -m) (assets exist for aarch64 and x86_64)" + die 3 "unsupported architecture: $(uname -m) (assets exist for aarch64, x86_64 and armv7)" ;; esac diff --git a/internal/modules/selfupdate.go b/internal/modules/selfupdate.go index 9783f33e..0c9bcd6b 100644 --- a/internal/modules/selfupdate.go +++ b/internal/modules/selfupdate.go @@ -23,7 +23,11 @@ const ( // binaryAssetName is the release asset for this build's architecture, so an // unsupported arch (e.g. mipsel before #236) never matches an existing asset // and the update is not offered/applied with a wrong-architecture binary (#237). +// The single 32-bit arm build is published as armv7 (GOARM=7, ipq40xx, #325). func binaryAssetName() string { + if runtime.GOARCH == "arm" { + return "netgrip-linux-armv7" + } return "netgrip-linux-" + runtime.GOARCH }