diff --git a/CHECKLIST.md b/CHECKLIST.md index 273d8a2..85d8c18 100644 --- a/CHECKLIST.md +++ b/CHECKLIST.md @@ -5,7 +5,7 @@ ## Работает сейчас - [x] Go server, SQLite/WAL, Docker/Compose и `/healthz`. -- [x] Go agent 0.6.3, heartbeat, команды, backoff и OpenWrt init integration. +- [x] Go agent 0.6.4, heartbeat, команды, backoff и OpenWrt init integration. - [x] APK/IPK и LuCI-пакет. - [x] Multi-user, роли admin/user, владение и передача роутеров. - [x] Профиль, e-mail, смена/сброс пароля и управление сессиями. diff --git a/RELEASES.md b/RELEASES.md index 7b63699..3c49e1b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -29,7 +29,7 @@ production upgrade even when the release is marked compatible. ## Agent releases -Tags use `agent-vMAJOR.MINOR.PATCH`, for example `agent-v0.6.3`. +Tags use `agent-vMAJOR.MINOR.PATCH`, for example `agent-v0.6.4`. An agent release contains the Go runtime, LuCI application and OpenWrt IPK/APK packages. Before tagging, the tag version must match `agentVersion` in the Go source and @@ -58,8 +58,8 @@ transition period; it should not silently reuse `v1`. git tag -a server-v0.8.0 -m "OpenWrt RMM Server 0.8.0" git push origin server-v0.8.0 -git tag -a agent-v0.6.3 -m "OpenWrt RMM Agent 0.6.3" -git push origin agent-v0.6.3 +git tag -a agent-v0.6.4 -m "OpenWrt RMM Agent 0.6.4" +git push origin agent-v0.6.4 ``` Pushing a server tag publishes the container image and creates a GitHub Release. Pushing diff --git a/ROADMAP.md b/ROADMAP.md index c86c9dc..b8023e9 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,6 +1,6 @@ # OpenWrt RMM — актуальный roadmap -Актуализировано: 2026-07-23. Текущая стабильная линия агента: `0.6.3`. +Актуализировано: 2026-07-23. Текущая стабильная линия агента: `0.6.4`. ## Цель продукта diff --git a/agent/README.md b/agent/README.md index 131f097..428690b 100644 --- a/agent/README.md +++ b/agent/README.md @@ -1,6 +1,6 @@ # OpenWrt RMM Agent -Current stable Go agent: `0.6.3`. It reports runtime health, pending command results, +Current stable Go agent: `0.6.4`. It reports runtime health, pending command results, and the last heartbeat transport error after connectivity is restored. Production Go agent for OpenWrt, with the shell implementation retained as a fallback runtime. diff --git a/agent/go/cmd/rmm-agent/main.go b/agent/go/cmd/rmm-agent/main.go index a12c070..de41c5e 100644 --- a/agent/go/cmd/rmm-agent/main.go +++ b/agent/go/cmd/rmm-agent/main.go @@ -23,7 +23,7 @@ import ( "time" ) -const agentVersion = "0.6.3" +const agentVersion = "0.6.4" type agentRuntimeHealth struct { StartedAt time.Time diff --git a/agent/go/cmd/rmm-agent/main_test.go b/agent/go/cmd/rmm-agent/main_test.go index 2ddaa1c..d9e0f98 100644 --- a/agent/go/cmd/rmm-agent/main_test.go +++ b/agent/go/cmd/rmm-agent/main_test.go @@ -9,7 +9,7 @@ import ( ) func TestAgentVersionIsStable(t *testing.T) { - if agentVersion != "0.6.3" { + if agentVersion != "0.6.4" { t.Fatalf("unexpected agent version %q", agentVersion) } } diff --git a/agent/package/luci-app-rmm-agent/README.md b/agent/package/luci-app-rmm-agent/README.md index fe7351e..6e9d2b9 100644 --- a/agent/package/luci-app-rmm-agent/README.md +++ b/agent/package/luci-app-rmm-agent/README.md @@ -67,7 +67,7 @@ application to the router. Do not copy or install the shell runtime at the same cd dist/rmm-openwrt-25.12.4-ramips-mt7621 sha256sum -c SHA256SUMS scp \ - rmm-agent-go-production-0.6.3-r1.apk \ + rmm-agent-go-production-0.6.4-r1.apk \ luci-app-rmm-agent-0.2.1-r2.apk \ root@ROUTER_IP:/tmp/ ``` @@ -76,7 +76,7 @@ Then install the locally built, unsigned packages over SSH: ```sh apk add --allow-untrusted \ - /tmp/rmm-agent-go-production-0.6.3-r1.apk \ + /tmp/rmm-agent-go-production-0.6.4-r1.apk \ /tmp/luci-app-rmm-agent-0.2.1-r2.apk /etc/init.d/rpcd restart /etc/init.d/uhttpd restart diff --git a/agent/package/rmm-agent-go-production/Makefile b/agent/package/rmm-agent-go-production/Makefile index 8bfc784..18bc769 100644 --- a/agent/package/rmm-agent-go-production/Makefile +++ b/agent/package/rmm-agent-go-production/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=rmm-agent-go-production -PKG_VERSION:=0.6.3 +PKG_VERSION:=0.6.4 PKG_RELEASE:=1 PKG_MAINTAINER:=RMM OpenWrt diff --git a/agent/package/rmm-agent-go-production/README.md b/agent/package/rmm-agent-go-production/README.md index da81a85..1d6e86a 100644 --- a/agent/package/rmm-agent-go-production/README.md +++ b/agent/package/rmm-agent-go-production/README.md @@ -34,5 +34,5 @@ opkg install /tmp/rmm-agent-go-production_*.ipk This package is intended for the final shell-to-Go migration when the router should keep the same RMM object identity. -Version `0.6.3` uses the cloud tunnel exclusively and no longer discovers or publishes the +Version `0.6.4` uses the cloud tunnel exclusively and no longer discovers or publishes the router's public WAN addresses. diff --git a/agent/package/rmm-agent-go/Makefile b/agent/package/rmm-agent-go/Makefile index e7de82f..3ee2d84 100644 --- a/agent/package/rmm-agent-go/Makefile +++ b/agent/package/rmm-agent-go/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=rmm-agent-go -PKG_VERSION:=0.6.3 +PKG_VERSION:=0.6.4 PKG_RELEASE:=1 PKG_MAINTAINER:=RMM OpenWrt diff --git a/deploy/luci-builder/Dockerfile b/deploy/luci-builder/Dockerfile index da55fd4..a31a3f7 100644 --- a/deploy/luci-builder/Dockerfile +++ b/deploy/luci-builder/Dockerfile @@ -166,26 +166,29 @@ RUN --mount=type=secret,id=openwrt_usign_secret_b64,uid=1000,required=false \ --mount=type=secret,id=openwrt_apk_secret_b64,uid=1000,required=false \ set -eu; \ export PATH="/home/builder/sdk/staging_dir/host/bin:${PATH}"; \ - test -n "${REPOSITORY_INDEX_REVISION}" \ - && mkdir -p /home/builder/artifacts \ - && find bin -type f \ + test -n "${REPOSITORY_INDEX_REVISION}"; \ + mkdir -p /home/builder/artifacts; \ + find bin -type f \ \( -name 'luci-app-rmm-agent*.apk' \ -o -name 'luci-app-rmm-agent*.ipk' \ -o -name 'rmm-agent*.apk' \ -o -name 'rmm-agent*.ipk' \) \ - -exec cp '{}' /home/builder/artifacts/ \; \ - && test -n "$(find /home/builder/artifacts -maxdepth 1 -type f \( -name '*.apk' -o -name '*.ipk' \) -print -quit)" \ - && cd /home/builder/artifacts \ - && if find . -maxdepth 1 -type f -name '*.ipk' -print -quit | grep -q .; then \ - /home/builder/sdk/scripts/ipkg-make-index.sh . > Packages; \ + -exec cp '{}' /home/builder/artifacts/ \;; \ + test -n "$(find /home/builder/artifacts -maxdepth 1 -type f \( -name '*.apk' -o -name '*.ipk' \) -print -quit)"; \ + cd /home/builder/artifacts; \ + if find . -maxdepth 1 -type f -name '*.ipk' -print -quit | grep -q .; then \ + MKHASH=/home/builder/sdk/staging_dir/host/bin/mkhash \ + /home/builder/sdk/scripts/ipkg-make-index.sh . > Packages; \ gzip -9nc Packages > Packages.gz; \ test -s Packages; \ test -s Packages.gz; \ if [ -s /run/secrets/openwrt_usign_secret_b64 ]; then \ base64 -d /run/secrets/openwrt_usign_secret_b64 > /tmp/usign.sec; \ chmod 600 /tmp/usign.sec; \ - /home/builder/sdk/staging_dir/host/bin/usign -S -m Packages -s /tmp/usign.sec; \ + /home/builder/sdk/staging_dir/host/bin/usign -S -m Packages \ + -s /tmp/usign.sec -x Packages.sig; \ /home/builder/sdk/staging_dir/host/bin/usign -V -m Packages \ + -x Packages.sig \ -p /home/builder/release-keys/usign/7fb0908fb6bc82c8; \ test -s Packages.sig; \ cp /home/builder/release-keys/usign/7fb0908fb6bc82c8 ./; \ @@ -221,14 +224,15 @@ RUN --mount=type=secret,id=openwrt_usign_secret_b64,uid=1000,required=false \ --output packages.adb \ ./*.apk; \ fi; \ - fi \ - && find . -maxdepth 1 -type f \( \ + fi; \ + find . -maxdepth 1 -type f \( \ -name '*.apk' -o -name '*.ipk' \ -o -name 'Packages' -o -name 'Packages.gz' -o -name 'Packages.sig' \ -o -name 'packages.adb' -o -name 'rmm-openwrt.pem' \ -o -name '????????????????' \) -print \ | LC_ALL=C sort \ - | xargs sha256sum > SHA256SUMS + | xargs sha256sum > SHA256SUMS; \ + test -s SHA256SUMS FROM scratch AS artifacts diff --git a/web/app.js b/web/app.js index f47d67b..ef8e245 100644 --- a/web/app.js +++ b/web/app.js @@ -38,7 +38,7 @@ const state = { let eventSource = null; let liveRefreshTimer = null; -const EXPECTED_AGENT_VERSION = "0.6.3"; +const EXPECTED_AGENT_VERSION = "0.6.4"; const els = { loginView: document.querySelector("#loginView"),