fix(ci): support ipset sockets and deployed image smoke checks
quality / changes (push) Successful in 6s
quality / commitlint (push) Skipped
quality / openapi (push) Successful in 28s
quality / web (push) Successful in 57s
quality / api (push) Successful in 1m35s
quality / linux-agent-smoke (push) Successful in 24s
quality / docker-check (push) Failing after 3m20s
CD / quality (push) Failing after 6m56s
CD / publish (push) Skipped
quality / changes (push) Successful in 6s
quality / commitlint (push) Skipped
quality / openapi (push) Successful in 28s
quality / web (push) Successful in 57s
quality / api (push) Successful in 1m35s
quality / linux-agent-smoke (push) Successful in 24s
quality / docker-check (push) Failing after 3m20s
CD / quality (push) Failing after 6m56s
CD / publish (push) Skipped
This commit is contained in:
1 parent
4db34f94f2
commit
57b7652d4d
11 files changed
+206
-15
No files matched your search
@@ -8,7 +8,7 @@ Local verification: `node --test scripts/ci/sqlite-backup.test.mjs` passed on Wi
|
||||
|
||||
The first pushed `linux-agent-smoke` job failed at `unshare: Operation not permitted`: its Gitea job container did not have the kernel capabilities needed by the nested namespace harness. The workflow now builds `scripts/ci/linux-agent-smoke.Dockerfile` and launches it using `linux-agent-container-smoke.sh`. Prerequisites and the checked-out agent/fixture/harness are copied into the helper image, so a remote Docker daemon needs no runner filesystem bind mounts.
|
||||
|
||||
The helper has its own network/PID/mount namespaces, `--network none`, a read-only image filesystem and a bounded temporary filesystem. It drops all capabilities except `SYS_ADMIN` (namespace/mount operations) and `NET_ADMIN` (veth, nftables and ipset inside the test namespaces). It retains Docker's default seccomp policy, enables no-new-privileges and never receives privileged mode, host networking/PIDs, host mounts or a Docker socket. On AppArmor-enabled daemons only this helper uses `apparmor=unconfined`, because Docker's default AppArmor policy denies the required mounts. See Docker's [capability guidance](https://docs.docker.com/engine/containers/run/) and [AppArmor policy guidance](https://docs.docker.com/engine/security/apparmor/).
|
||||
The helper has its own network/PID/mount namespaces, `--network none`, a read-only image filesystem and a bounded temporary filesystem. It drops all capabilities except `SYS_ADMIN` (namespace/mount operations), `NET_ADMIN` (veth, nftables and ipset inside the test namespaces), and `NET_RAW` (the iptables set extension opens a raw socket while querying ipset). It retains Docker's default seccomp policy, enables no-new-privileges and never receives privileged mode, host networking/PIDs, host mounts or a Docker socket. On AppArmor-enabled daemons only this helper uses `apparmor=unconfined`, because Docker's default AppArmor policy denies the required mounts. See Docker's [capability guidance](https://docs.docker.com/engine/containers/run/) and [AppArmor policy guidance](https://docs.docker.com/engine/security/apparmor/).
|
||||
|
||||
The original harness still creates and verifies separate network/mount/PID namespaces before firewall mutations. A preflight namespace probe fails clearly when the daemon/kernel does not support the required isolation; there is no skip, privileged retry or host-firewall fallback. The daemon must support namespaces, IPv6, veth, nftables, iptables and ipset; the helper cannot load missing host kernel modules. Its immutable image ID is used for execution and its container/image are cleaned up while preserving the original test exit code.
|
||||
|
||||
@@ -98,3 +98,9 @@ A second fresh Windows in-memory run of the original mixed profile passed all 11
|
||||
The final fresh run used the separated profiles on Windows Node 25.5 with an in-memory DB and no CPU/RAM quota. All 1611 requests passed with zero rate limits, exact report-ID/sequence and duplicate ACK checks, four raw rows per agent, final per-agent 300 dropped/600 accepted and fleet totals 30000/60000. The 100k import summary remained below 256 bytes. Burst profile: 1000 requests at concurrency 10, new-ingestion p95 372.753ms (300 samples), timeseries p95 782.623ms and cold-policy p95 3451.412ms. Steady profile: 400 requests, two workers paced at 1200ms; new ingestion 100 samples p95 11.0855ms/max 14.4917ms, timeseries 100 samples p95 8.0675ms/max 10.7258ms, duplicate retries 100 samples p95 7.5481ms and summaries 100 samples p95 3.6905ms. This verifies the revised harness and local correctness. It does not prove native 2-vCPU/4GB capacity or establish a performance improvement. The actual constrained CI threshold remains pending execution.
|
||||
|
||||
Builder concurrency correction: each quality/publication job uses its own run-ID/attempt builder, with setup-buildx cleanup enabled. The registry cache is durable; local builder state is disposable. The verification script inspects the actual container configuration before use. Jobs never remove a shared builder, so concurrent PRs cannot tear down another build. The old persistent `evofw` builder is no longer selected; remove its stale container/state only during an idle-runner maintenance window after confirming no legacy job is using it.
|
||||
|
||||
The subsequent ipset smoke failed with `iptables-restore ... Can't open socket to ipset`. The [iptables set extension source](https://android.googlesource.com/platform/external/iptables/+/8902cb0d42754a35febbc79c077bca770c477bf1/extensions/libxt_set.h) opens an `AF_INET` raw socket in `get_version` before querying the set API. The [Linux raw socket manual](https://man7.org/linux/man-pages/man7/raw.7.html) requires `CAP_NET_RAW` for this operation. The helper therefore adds only `NET_RAW` to its existing capabilities; it keeps its isolated network, default seccomp, and all other restrictions. The wrapper regression checks the exact three-capability set, exit propagation, and cleanup. This source-based fix still requires the next Linux CI smoke to confirm native ipset execution; the Windows test does not execute Docker or kernel commands.
|
||||
|
||||
The published upgrade baseline subsequently started successfully and returned `/ready` 200, but the smoke marker failed while resolving `better-sqlite3` through a synthetic `/app/node_modules/@evofw/db/package.json` path. The marker now creates one uniquely named static list with one CIDR through the public API, captures its ID and verifies that same ID/name/entry across upgrade, restart and restoration. Later verification never recreates a missing marker. This API shape was checked against the previous `aa47584` list routes and accepts their HTTP 200 creation response as well as newer HTTP 201 responses. It makes no assumptions about the old image's dependency layout; native SQLite startup and persistence are still exercised by readiness and actual API writes/reads.
|
||||
|
||||
The backup utility and benchmark fixture had the same pnpm resolution assumption. Both now resolve the DB package's real filesystem location before constructing its dependency resolver. The backup regression uses an isolated pnpm-shaped symlink/junction tree, removes the former `NODE_PATH` workaround, demonstrates that the synthetic resolver fails and verifies the real fixture loader plus WAL backup/offline restore. That regression passed locally after the required Windows sandbox escalation. The marker regression runs the actual embedded Node program with a fake public API: old/new response codes, retained ID, missing rows and lost entries are covered and passed. CI runs this marker regression beside the backup test, and the benchmark wrapper regression runs before its real image benchmark. These local checks do not establish a successful native upgrade/backup/benchmark; those remain pending CI. The nft namespace backend has already passed native IPv4/IPv6 denial, drift repair, invalid-candidate preservation and unrelated-table preservation; ipset and the full built-image sequence still require the corrected run.
|
||||
Reference in new issue
Block a user