Files
awoooi/ops/runner/test_check_awoooi_non110_runner_readiness.py
Your Name 62820cabbc
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 56s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
fix(runner): recover disabled non110 service from keepalive
2026-07-01 09:10:32 +08:00

356 lines
12 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import os
import subprocess
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
VERIFIER = ROOT / "ops/runner/check-awoooi-non110-runner-readiness.sh"
def _write_fake_bin(path: Path, name: str, body: str) -> None:
target = path / name
target.write_text(body, encoding="utf-8")
target.chmod(0o755)
def _write_runner_config(path: Path) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(
"""
runner:
capacity: 1
labels:
- "awoooi-host:host"
- "awoooi-ubuntu:docker://192.168.0.110:5000/awoooi/ci-runner:act-22.04"
""".strip()
+ "\n",
encoding="utf-8",
)
def _write_unit(
path: Path,
binary_path: Path,
config_path: Path,
registration_path: Path,
) -> None:
path.write_text(
f"""
[Unit]
ConditionPathExists={registration_path}
[Service]
ExecStart={binary_path} daemon --config {config_path}
Restart=always
CPUQuota=200%
MemoryMax=8G
TasksMax=512
NoNewPrivileges=true
""".strip()
+ "\n",
encoding="utf-8",
)
def _write_path_unit(path: Path, registration_path: Path) -> None:
path.write_text(
f"""
[Unit]
Description=Watch AWOOOI non-110 runner registration metadata
[Path]
PathExists={registration_path}
Unit=awoooi-non110-runner-autostart.service
[Install]
WantedBy=default.target
""".strip()
+ "\n",
encoding="utf-8",
)
def _write_keepalive_timer(path: Path) -> None:
path.write_text(
"""
[Unit]
Description=Periodically verify AWOOOI non-110 runner user service is active
[Timer]
OnBootSec=30s
OnUnitInactiveSec=60s
AccuracySec=10s
Unit=awoooi-non110-runner-keepalive.service
[Install]
WantedBy=timers.target
""".strip()
+ "\n",
encoding="utf-8",
)
def _write_keepalive_service(path: Path) -> None:
path.write_text(
"""
[Unit]
Description=Keep AWOOOI non-110 runner active while enable sentinel exists
[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl --user daemon-reload
ExecStart=-/usr/bin/systemctl --user reset-failed awoooi-non110-runner.service
ExecStart=/usr/bin/systemctl --user enable awoooi-non110-runner.service
ExecStart=/usr/bin/systemctl --user start awoooi-non110-runner.service
RemainAfterExit=no
""".strip()
+ "\n",
encoding="utf-8",
)
def _run_verifier(
tmp_path: Path,
registration_path: Path,
*,
active_service: bool = True,
unit_target_matches: bool = True,
unmanaged_runner_container: bool = False,
keepalive_timer: bool = True,
keepalive_service_failed: bool = False,
) -> subprocess.CompletedProcess[str]:
fake_bin = tmp_path / "bin"
unit_dir = tmp_path / "units"
fake_bin.mkdir()
unit_dir.mkdir()
_write_fake_bin(
fake_bin,
"systemctl",
f"""#!/usr/bin/env bash
set -euo pipefail
if [ "${{1:-}}" = "--user" ]; then shift; fi
cmd="${{1:-}}"; unit="${{2:-}}"
case "$cmd" in
show)
if [ "${{2:-}}" = "-p" ]; then
unit="${{1:-}}"
fi
if [ -f "{unit_dir}/$unit" ]; then
if [[ "$unit" == *.path ]]; then
printf 'LoadState=loaded\\nActiveState=active\\nUnitFileState=enabled\\nMainPID=0\\n'
exit 0
fi
if [[ "$unit" == *.timer ]]; then
printf 'LoadState=loaded\\nActiveState=active\\nUnitFileState=enabled\\nMainPID=0\\n'
exit 0
fi
if [[ "$unit" == *keepalive.service ]]; then
printf 'LoadState=loaded\\nActiveState={"failed" if keepalive_service_failed else "inactive"}\\nUnitFileState=static\\nMainPID=0\\nResult={"exit-code" if keepalive_service_failed else "success"}\\nExecMainStatus={"1" if keepalive_service_failed else "0"}\\n'
exit 0
fi
printf 'LoadState=loaded\\nActiveState={"active" if active_service else "inactive"}\\nUnitFileState=disabled\\nMainPID={"1234" if active_service else "0"}\\n'
exit 0
fi
if [ "${{2:-}}" = "-p" ] && [ "${{3:-}}" = "LoadState" ]; then
printf 'not-found\\n'
exit 0
fi
printf 'LoadState=not-found\\nActiveState=inactive\\nUnitFileState=\\nMainPID=0\\n'
exit 0
;;
cat)
if [ -f "{unit_dir}/$unit" ]; then cat "{unit_dir}/$unit"; exit 0; fi
exit 1
;;
esac
exit 1
""",
)
unmanaged_runner_output = (
"printf 'condescending_wilbur|gitea/act_runner:latest\\n'"
if unmanaged_runner_container
else "exit 0"
)
_write_fake_bin(
fake_bin,
"docker",
f"""#!/usr/bin/env bash
if [ "${{1:-}}" = "ps" ]; then
if printf '%s\\n' "$*" | grep -q 'Image'; then
{unmanaged_runner_output}
exit 0
fi
exit 0
fi
exit 0
""",
)
_write_fake_bin(
fake_bin,
"pgrep",
"""#!/usr/bin/env bash
exit 1
""",
)
_write_fake_bin(
fake_bin,
"ip",
"""#!/usr/bin/env bash
if [ "${1:-}" = "-o" ] && [ "${2:-}" = "-4" ] && [ "${3:-}" = "addr" ]; then
printf '1: lo inet 127.0.0.1/8 scope host lo\\n'
printf '2: eth0 inet 192.168.0.188/24 brd 192.168.0.255 scope global eth0\\n'
exit 0
fi
exit 1
""",
)
config_path = tmp_path / "config.yaml"
binary_path = tmp_path / "act_runner"
_write_runner_config(config_path)
binary_path.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
binary_path.chmod(0o755)
unit_binary_path = binary_path if unit_target_matches else tmp_path / "other_act_runner"
unit_config_path = config_path if unit_target_matches else tmp_path / "other_config.yaml"
_write_unit(
unit_dir / "awoooi-non110-runner.service",
unit_binary_path,
unit_config_path,
registration_path,
)
_write_unit(
unit_dir / "awoooi-non110-runner-rollback.service",
unit_binary_path,
unit_config_path,
registration_path,
)
_write_path_unit(
unit_dir / "awoooi-non110-runner-autostart.path",
registration_path,
)
if keepalive_timer:
_write_keepalive_service(unit_dir / "awoooi-non110-runner-keepalive.service")
_write_keepalive_timer(unit_dir / "awoooi-non110-runner-keepalive.timer")
env = {
**os.environ,
"PATH": f"{fake_bin}:{os.environ['PATH']}",
"TARGET_HOST_IP": "",
"FORBIDDEN_HOST_IPS": "",
"RUNNER_CONFIG_PATHS": str(config_path),
"RUNNER_BINARY_PATHS": str(binary_path),
"RUNNER_SERVICE_NAMES": "awoooi-non110-runner.service",
"RUNNER_AUTOSTART_PATH_UNIT_NAMES": "awoooi-non110-runner-autostart.path",
"RUNNER_KEEPALIVE_SERVICE_UNIT_NAMES": "awoooi-non110-runner-keepalive.service",
"RUNNER_KEEPALIVE_TIMER_UNIT_NAMES": "awoooi-non110-runner-keepalive.timer",
"ROLLBACK_UNIT_NAMES": "awoooi-non110-runner-rollback.service",
"RUNNER_REGISTRATION_PATHS": str(registration_path),
"MAX_HEAVY_PROCESS_COUNT": "0",
}
return subprocess.run(
["bash", str(VERIFIER)],
check=False,
env=env,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
def test_non110_readiness_blocks_without_registration_state(tmp_path: Path) -> None:
result = _run_verifier(tmp_path, tmp_path / ".runner")
assert result.returncode == 1
assert "BLOCKER runner_registration_missing" in result.stdout
assert "AWOOOI_NON110_RUNNER_READY=0" in result.stdout
assert "raw_runner_registration_read=false" in result.stdout
assert (
"safe_next_step=run_register_awoooi_non110_runner_script_without_printing_token_then_autostart_path_will_enable_service_and_rerun_this_verifier"
in result.stdout
)
assert "RUNNER_AUTOSTART_PATH unit=awoooi-non110-runner-autostart.path installed=1" in result.stdout
assert (
"RUNNER_AUTOSTART_PATH_WATCH unit=awoooi-non110-runner-autostart.path registration_watch=1 active=1 enabled=1"
in result.stdout
)
assert "READY_AUTOSTART_PATH_COUNT=1" in result.stdout
assert "RUNNER_KEEPALIVE_TIMER unit=awoooi-non110-runner-keepalive.timer installed=1" in result.stdout
assert "BLOCKER runner_keepalive_timer_not_ready" not in result.stdout
assert "BLOCKER runner_keepalive_service_not_ready" not in result.stdout
def test_non110_readiness_accepts_registration_state_presence_without_reading_it(
tmp_path: Path,
) -> None:
registration_path = tmp_path / ".runner"
registration_path.write_text("secret-token-like-content-not-printed\n", encoding="utf-8")
result = _run_verifier(tmp_path, registration_path)
assert result.returncode == 0, result.stdout + result.stderr
assert "RUNNER_REGISTRATION" in result.stdout
assert "present=1" in result.stdout
assert "content_read=false" in result.stdout
assert "registration_condition=1" in result.stdout
assert "RUNNER_KEEPALIVE_SERVICE unit=awoooi-non110-runner-keepalive.service installed=1" in result.stdout
assert "READY_KEEPALIVE_SERVICE_COUNT=1" in result.stdout
assert "RUNNER_KEEPALIVE_TIMER unit=awoooi-non110-runner-keepalive.timer installed=1" in result.stdout
assert "READY_KEEPALIVE_TIMER_COUNT=1" in result.stdout
assert "secret-token-like-content" not in result.stdout
assert "AWOOOI_NON110_RUNNER_READY=1" in result.stdout
def test_non110_readiness_blocks_failed_keepalive_service(tmp_path: Path) -> None:
registration_path = tmp_path / ".runner"
registration_path.write_text("secret-token-like-content-not-printed\n", encoding="utf-8")
result = _run_verifier(
tmp_path,
registration_path,
keepalive_service_failed=True,
)
assert result.returncode == 1
assert "BLOCKER runner_keepalive_service_failed:awoooi-non110-runner-keepalive.service" in result.stdout
assert "BLOCKER runner_keepalive_service_not_ready" in result.stdout
assert "secret-token-like-content" not in result.stdout
assert "AWOOOI_NON110_RUNNER_READY=0" in result.stdout
def test_non110_readiness_blocks_registered_runner_without_keepalive_timer(
tmp_path: Path,
) -> None:
registration_path = tmp_path / ".runner"
registration_path.write_text("secret-token-like-content-not-printed\n", encoding="utf-8")
result = _run_verifier(tmp_path, registration_path, keepalive_timer=False)
assert result.returncode == 1
assert "BLOCKER runner_keepalive_timer_not_ready" in result.stdout
assert "READY_KEEPALIVE_TIMER_COUNT=0" in result.stdout
assert "secret-token-like-content" not in result.stdout
assert "AWOOOI_NON110_RUNNER_READY=0" in result.stdout
def test_non110_readiness_blocks_service_target_mismatch(tmp_path: Path) -> None:
registration_path = tmp_path / ".runner"
registration_path.write_text("secret-token-like-content-not-printed\n", encoding="utf-8")
result = _run_verifier(tmp_path, registration_path, unit_target_matches=False)
assert result.returncode == 1
assert "BLOCKER runner_service_target_mismatch:awoooi-non110-runner.service" in result.stdout
assert "RUNNER_SERVICE_TARGETS unit=awoooi-non110-runner.service" in result.stdout
assert "AWOOOI_NON110_RUNNER_READY=0" in result.stdout
def test_non110_readiness_blocks_unmanaged_act_runner_container(tmp_path: Path) -> None:
registration_path = tmp_path / ".runner"
registration_path.write_text("secret-token-like-content-not-printed\n", encoding="utf-8")
result = _run_verifier(
tmp_path,
registration_path,
unmanaged_runner_container=True,
)
assert result.returncode == 1
assert "UNMANAGED_RUNNER_CONTAINERS=condescending_wilbur" in result.stdout
assert (
"BLOCKER unmanaged_runner_containers_present:condescending_wilbur"
in result.stdout
)
assert "secret-token-like-content" not in result.stdout