Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/registry-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@ name: Registry KV sync
# The plugins.nself.org worker serves the catalog from the repo, but its KV copy (stats.lastSync) only moves when
# POST /api/sync runs. Nothing called it after 2026-06-23, which kept drill-catalog-freshness red (D-0051). A daily call
# keeps lastSync under the drill's 36 hour limit.
# A merge to main that changes a projection the worker serves (catalog.json carries the bundle membership that /bundles.json
# is built from, registry.json the plugin versions) also calls it, so drill-catalog-freshness is not red between that merge
# and the next daily run (D-1480). Same token as the daily run; scripts/ci/tests/test_registry_sync_triggers.py holds the paths.

on:
schedule:
- cron: '17 5 * * *'
push:
branches: [main]
paths:
- 'catalog.json'
- 'registry.json'
- 'counts.json'
workflow_dispatch:

permissions:
Expand Down
52 changes: 52 additions & 0 deletions scripts/ci/tests/test_registry_sync_triggers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Tests for the triggers of .github/workflows/registry-sync.yml (D-1480).

The worker's served catalog only moves when POST /api/sync runs. The daily schedule stays, and a push to main that
changes a projection the drill compares (catalog.json, registry.json, counts.json) must run it too, or
drill-catalog-freshness stays red from the merge until the next daily run. The workflow is read as text (no YAML
library on the runner), so this checks the `on:` block only.
"""

from pathlib import Path
import re
import unittest

WORKFLOW = Path(__file__).resolve().parents[3] / ".github" / "workflows" / "registry-sync.yml"
SERVED = {"catalog.json", "registry.json", "counts.json"}


def on_block(text):
m = re.search(r"^on:\n((?:[ \t]+.*\n|[ \t]*\n)+)", text, re.M)
assert m, "no top-level on: block"
return m.group(1)


def section(block, key):
"""The lines indented under ` key:` inside the on: block."""
m = re.search(r"^ " + key + r":\n((?: .*\n|[ \t]*\n)+)", block, re.M)
return m.group(1) if m else None


class RegistrySyncTriggers(unittest.TestCase):
def setUp(self):
self.text = WORKFLOW.read_text()
self.block = on_block(self.text)

def test_daily_schedule_stays(self):
sched = section(self.block, "schedule")
self.assertIsNotNone(sched, "the daily schedule is gone")
self.assertRegex(sched, r"cron:\s*'17 5 \* \* \*'")

def test_push_to_main_on_served_projections(self):
push = section(self.block, "push")
self.assertIsNotNone(push, "no push trigger")
self.assertRegex(push, r"branches:\s*\[main\]")
paths = set(re.findall(r"^\s+-\s+['\"]?([^'\"\s]+)['\"]?\s*$", push.split("paths:")[1], re.M))
self.assertEqual(paths, SERVED)

def test_no_new_secret(self):
secrets = set(re.findall(r"secrets\.([A-Z0-9_]+)", self.text))
self.assertEqual(secrets, {"CLOUDFLARE_WORKER_SYNC_TOKEN"})


if __name__ == "__main__":
unittest.main()
27 changes: 26 additions & 1 deletion scripts/drill/isolation-levels/run
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,32 @@ for tool in jq go; do
command -v "$tool" >/dev/null 2>&1 || { say "$tool is required"; exit 2; }
done
work=$(mktemp -d "${TMPDIR:-/tmp}/isolation-levels.XXXXXX") || exit 2
trap 'rm -rf "$work"' EXIT
# probes: "runtime:id" for every engine probe container (label nself.ci.probe=1, see internal/exec/runtime_probe.go) a runtime
# holds, running or not.
probes() {
local c id
for c in docker podman; do
command -v "$c" >/dev/null 2>&1 || continue
for id in $("$c" ps -aq --filter label=nself.ci.probe=1 2>/dev/null || true); do printf '%s:%s\n' "$c" "$id"; done
done
}
# The legs start the engine's gVisor probe container; one that outlives its leg (a killed CLI, a hung start) would keep running
# into the next drill, and scenario-01-local-only refuses to cut the network while any container is up (D-1481). So on exit remove
# the probe containers this run left, and only those: the ones that were there before it started belong to somebody else.
probes_before=$(probes)
# shellcheck disable=SC2329 # runs from the EXIT trap
cleanup() {
local p
for p in $(probes); do
case "
$probes_before
" in *"
$p
"*) ;; *) "${p%%:*}" rm -f "${p#*:}" >/dev/null 2>&1 || true ;; esac
done
rm -rf "$work"
}
trap cleanup EXIT
checks=$work/checks.ndjson
: >"$checks"
started=$(date -u +%Y-%m-%dT%H:%M:%SZ)
Expand Down
11 changes: 11 additions & 0 deletions scripts/drill/isolation-levels/selftest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ cat >"$bin/docker" <<'F'
case "$1" in
info) if [ "$2" = "--format" ]; then if [ -z "${FAKE_NO_RUNSC:-}" ]; then echo '{"runc":{},"runsc":{}}'; else echo '{"runc":{}}'; fi; fi; exit 0 ;;
image | pull) exit 0 ;;
ps) [ -z "${FAKE_PROBES:-}" ] || cat "$FAKE_PROBES" 2>/dev/null; exit 0 ;;
rm) echo "$*" >>"$FAKE_RM_LOG"; exit 0 ;;
esac
exit 0
F
cat >"$bin/go" <<'F'
#!/bin/sh
for a in "$@"; do pkg=$a; done
echo "=== RUN TestX"
[ -z "${FAKE_GO_LEAK:-}" ] || echo "$FAKE_GO_LEAK" >>"$FAKE_PROBES"
case "$pkg" in
*"${FAKE_GO_FAIL:-NONE}"*) echo "--- FAIL: TestX (0.00s)"; echo "FAIL"; exit 1 ;;
*"${FAKE_GO_SKIP:-NONE}"*) echo "--- SKIP: TestX (0.00s)"; echo "ok"; exit 0 ;;
Expand Down Expand Up @@ -123,4 +126,12 @@ grep -q "^args: --no-status --pipeline drills --job drill-isolation-levels$" "$w
grep -q "v15: 1" "$work/direct.log" || fail "direct env: $(cat "$work/direct.log")"
grep -q "repo: $(cd "$here/../../.." && pwd) " "$work/direct.log" || fail "direct repo: $(cat "$work/direct.log")"
echo "ok direct"
# 10. A probe container the legs leave behind is removed on exit; one that was there before the drill started is not.
printf 'oldprobe\n' >"$work/probes"
: >"$work/rm.log"
drill leak FAKE_PROBES="$work/probes" FAKE_RM_LOG="$work/rm.log" FAKE_GO_LEAK=newprobe
[ "$(rc leak)" = 0 ] || fail "leak: exit $(rc leak): $(cat "$work/leak.err")"
grep -q '^rm -f newprobe$' "$work/rm.log" || fail "leak: the probe left by the legs was not removed: $(cat "$work/rm.log")"
! grep -q oldprobe "$work/rm.log" || fail "leak: removed a probe container that was there before the drill: $(cat "$work/rm.log")"
echo "ok leak"
echo "all ok"
Loading