diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index ad5095dd..9ab435ef 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -49036,3 +49036,19 @@ production browser smoke: - 沒有讀、複製、貼上、外送 runner token / secret / `.env` / raw sessions / SQLite / auth。 - 沒有啟動 188 runner service、沒有重開 110 runner、沒有 GitHub API / gh / GitHub Actions、沒有 force push。 - Gitea CD 仍需等 non-110 runner 完成外部安全註冊並讀回 `AWOOOI_NON110_RUNNER_READY=1` 後才可承接。 + +## 2026-06-29 — 08:58 non-110 runner autostart controlled apply + +**完成內容**: +- 188 `/home/ollama/act-runner-awoooi` 已套用 user-level autostart path / service source:`awoooi-non110-runner-autostart.path` 監看 `.runner` metadata 出現後才觸發 `awoooi-non110-runner.service` enable/start。 +- installer `--apply` 讀回 `AUTOSTART_PATH_ENABLE_PERFORMED=1`、`SERVICE_START_PERFORMED=0`、`SERVICE_ENABLE_PERFORMED=0`;runner 本體維持 `inactive/disabled`,避免未註冊狀態誤開 CD lane。 +- 188 systemd readback:autostart path `LoadState=loaded`、`ActiveState=active`、`UnitFileState=enabled`;autostart service `inactive/static`;runner service `inactive/disabled`。 + +**verifier readback**: +- `check-awoooi-non110-runner-readiness.sh`:`READY_CONFIG_COUNT=1`、`READY_BINARY_COUNT=1`、`READY_REGISTRATION_COUNT=0`、`READY_SERVICE_COUNT=1`、`READY_ACTIVE_SERVICE_COUNT=0`、`BLOCKER_COUNT=3`、`AWOOOI_NON110_RUNNER_READY=0`。 +- blockers 仍為 `runner_registration_missing`、`runner_service_not_active:awoooi-non110-runner.service`、`no_active_runner_service`;safe next step 仍是互動 TTY 執行 safe registration helper,不得由 Codex 讀取或輸入 runner token。 + +**仍維持**: +- 沒有讀、複製、貼上、外送 runner token / secret / `.runner` 內容、`.env`、raw sessions / SQLite / auth。 +- 沒有重開 110 legacy / generic runner、沒有恢復 `ubuntu-latest` / `self-hosted` 泛用 label、沒有把 pressure gate 改成 warn-only。 +- Gitea CD / production UI bundle smoke 仍需等 `AWOOOI_NON110_RUNNER_READY=1` 後承接;目前不得宣稱 runner lane 已 reopened。 diff --git a/ops/runner/install-awoooi-non110-runner-user-service.sh b/ops/runner/install-awoooi-non110-runner-user-service.sh index b6bbf245..3eb5369a 100755 --- a/ops/runner/install-awoooi-non110-runner-user-service.sh +++ b/ops/runner/install-awoooi-non110-runner-user-service.sh @@ -14,6 +14,8 @@ RUNNER_REGISTRATION="${RUNNER_REGISTRATION:-${RUNNER_DIR}/.runner}" ENABLE_SENTINEL="${ENABLE_SENTINEL:-${RUNNER_DIR}/.awoooi-non110-runner-enabled}" SERVICE_NAME="${SERVICE_NAME:-awoooi-non110-runner.service}" ROLLBACK_SERVICE_NAME="${ROLLBACK_SERVICE_NAME:-awoooi-non110-runner-rollback.service}" +AUTOSTART_SERVICE_NAME="${AUTOSTART_SERVICE_NAME:-awoooi-non110-runner-autostart.service}" +AUTOSTART_PATH_NAME="${AUTOSTART_PATH_NAME:-awoooi-non110-runner-autostart.path}" USER_SERVICE_DIR="${USER_SERVICE_DIR:-${RUNNER_HOME}/.config/systemd/user}" RUNNER_LABELS="${RUNNER_LABELS:-awoooi-non110-host:host,awoooi-non110-ubuntu:docker://192.168.0.110:5000/awoooi/ci-runner:act-22.04}" WRITE_CONFIG_IF_MISSING="${WRITE_CONFIG_IF_MISSING:-1}" @@ -45,6 +47,14 @@ rollback_service_path() { printf '%s/%s\n' "$USER_SERVICE_DIR" "$ROLLBACK_SERVICE_NAME" } +autostart_service_path() { + printf '%s/%s\n' "$USER_SERVICE_DIR" "$AUTOSTART_SERVICE_NAME" +} + +autostart_path_path() { + printf '%s/%s\n' "$USER_SERVICE_DIR" "$AUTOSTART_PATH_NAME" +} + metadata_path() { local path="$1" if [ -e "$path" ]; then @@ -166,11 +176,45 @@ Type=oneshot ExecStart=-/usr/bin/systemctl --user stop ${SERVICE_NAME} ExecStart=-/usr/bin/systemctl --user disable ${SERVICE_NAME} ExecStart=-/usr/bin/systemctl --user reset-failed ${SERVICE_NAME} +ExecStart=-/usr/bin/systemctl --user stop ${AUTOSTART_PATH_NAME} +ExecStart=-/usr/bin/systemctl --user disable ${AUTOSTART_PATH_NAME} +ExecStart=-/usr/bin/systemctl --user reset-failed ${AUTOSTART_SERVICE_NAME} ExecStart=-/usr/bin/rm -f ${ENABLE_SENTINEL} RemainAfterExit=no EOF } +write_autostart_units() { + cat >"$(autostart_service_path)" <"$(autostart_path_path)" </dev/null || true systemctl --user show "$ROLLBACK_SERVICE_NAME" -p LoadState -p ActiveState -p UnitFileState -p MainPID --no-pager 2>/dev/null || true + systemctl --user show "$AUTOSTART_PATH_NAME" -p LoadState -p ActiveState -p UnitFileState -p MainPID --no-pager 2>/dev/null || true } apply_units() { @@ -203,9 +252,12 @@ apply_units() { write_default_config write_runner_service write_rollback_service - chmod 0644 "$(service_path)" "$(rollback_service_path)" + write_autostart_units + chmod 0644 "$(service_path)" "$(rollback_service_path)" "$(autostart_service_path)" "$(autostart_path_path)" systemd_user_reload + systemctl --user enable --now "$AUTOSTART_PATH_NAME" >/dev/null printf 'APPLY_PERFORMED=1\n' + printf 'AUTOSTART_PATH_ENABLE_PERFORMED=1\n' printf 'SERVICE_START_PERFORMED=0\n' printf 'SERVICE_ENABLE_PERFORMED=0\n' } @@ -234,6 +286,9 @@ rollback_runner() { systemctl --user stop "$SERVICE_NAME" >/dev/null 2>&1 || true systemctl --user disable "$SERVICE_NAME" >/dev/null 2>&1 || true systemctl --user reset-failed "$SERVICE_NAME" >/dev/null 2>&1 || true + systemctl --user stop "$AUTOSTART_PATH_NAME" >/dev/null 2>&1 || true + systemctl --user disable "$AUTOSTART_PATH_NAME" >/dev/null 2>&1 || true + systemctl --user reset-failed "$AUTOSTART_SERVICE_NAME" >/dev/null 2>&1 || true rm -f "$ENABLE_SENTINEL" printf 'ROLLBACK_PERFORMED=1\n' } diff --git a/ops/runner/test_register_awoooi_non110_runner.py b/ops/runner/test_register_awoooi_non110_runner.py index 9f706710..86d850d7 100644 --- a/ops/runner/test_register_awoooi_non110_runner.py +++ b/ops/runner/test_register_awoooi_non110_runner.py @@ -61,6 +61,18 @@ def test_user_installer_has_no_token_argv_path() -> None: assert "never\n# registers a runner" in installer +def test_user_installer_autostarts_only_after_registration_metadata() -> None: + installer = USER_SERVICE_INSTALLER.read_text(encoding="utf-8") + assert "AUTOSTART_PATH_NAME" in installer + assert "PathExists=${RUNNER_REGISTRATION}" in installer + assert "Unit=${AUTOSTART_SERVICE_NAME}" in installer + assert "ExecStart=/usr/bin/test -s ${RUNNER_REGISTRATION}" in installer + assert "ExecStart=/usr/bin/touch ${ENABLE_SENTINEL}" in installer + assert "systemctl --user enable --now ${SERVICE_NAME}" in installer + assert 'systemctl --user enable --now "$AUTOSTART_PATH_NAME"' in installer + assert 'systemctl --user disable "$AUTOSTART_PATH_NAME"' in installer + + def test_register_helper_dry_run_requires_no_token(tmp_path: Path) -> None: runner_dir = tmp_path / "runner" runner_dir.mkdir(parents=True)