From 9f02e0faf23eccf0c4ed62be2ec14d004c59ba97 Mon Sep 17 00:00:00 2001 From: Anthony Date: Wed, 1 Jul 2026 08:27:58 +0000 Subject: [PATCH 1/2] ci(deploy): preempt self-update timer so it can't starve the deploy lock The self-update systemd timer redeploys from source (no SKIP_BUILD) and can hold setup.sh's flock for >5min while compiling on a tiny droplet. When it fires close to a CI push it starves the deploy, which waits the full 5min on the lock and then fails with 'another setup.sh run is in progress (lock held >5m)'. The CI push is authoritative (ships prebuilt binaries + resets to the exact commit), so stop any in-flight timer run to release the lock and pause the timer before taking it. setup.sh re-enables the timer at the end of its run. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/deploy.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 70e5fbe..a35c3ea 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -134,6 +134,14 @@ jobs: fi git -C "$SRC" fetch --depth 1 origin "$BRANCH" git -C "$SRC" reset --hard "origin/$BRANCH" + # Preempt the self-update timer. It redeploys from source (no + # SKIP_BUILD) and can hold setup.sh's flock for >5min while compiling + # on this tiny droplet, which would starve and time out the deploy + # below. This CI push is authoritative (prebuilt binaries + reset to + # the exact commit), so stop any in-flight timer run to release the + # lock and pause the timer so it can't re-fire mid-deploy; setup.sh + # re-enables the timer at the end of its run. + systemctl stop agentbbs-update.timer agentbbs-update.service 2>/dev/null || true # Install the runner-built binaries, then tell setup.sh not to compile. install -m 0755 /tmp/agentbbs-deploy-agentbbs /usr/local/bin/agentbbs install -m 0755 /tmp/agentbbs-deploy-ascii-live /usr/local/bin/ascii-live From 9af7857c985ce71a61579c2b10912740add4d969 Mon Sep 17 00:00:00 2001 From: Anthony Date: Wed, 1 Jul 2026 08:31:13 +0000 Subject: [PATCH 2/2] test(files): isolate over-quota test from seeded-README baseline TestWebSaveOverQuotaPreservesExistingFile set quota=5 but left sess.used at the newSession baseline, which already counts the README.txt that ensureUserPub seeds into /public (added in d19c5c4). That baseline alone exceeds 5 bytes, so the initial 2-byte save was rejected with 'quota exceeded' before the test could exercise the over-quota replace. Reset sess.used to 0 after setting the tiny quota, mirroring TestQuotaEnforced, so the writer starts from a clean gauge. Co-Authored-By: Claude Opus 4.8 --- internal/files/files_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/files/files_test.go b/internal/files/files_test.go index c73e81a..577cce5 100644 --- a/internal/files/files_test.go +++ b/internal/files/files_test.go @@ -173,6 +173,7 @@ func TestWebSaveOverQuotaPreservesExistingFile(t *testing.T) { svc, _, u := newTestService(t) sess, _ := svc.newSession(u) sess.quota = 5 + sess.used.Store(0) // isolate the writer from the seeded-README baseline if _, err := sess.webSave("/me/note.txt", strings.NewReader("ok")); err != nil { t.Fatalf("initial save failed: %v", err)