157 lines
4.8 KiB
Bash
Executable File
157 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
RUNNER_DIR="${RUNNER_DIR:-/home/wooo/act-runner}"
|
|
RUNNER_USER="${RUNNER_USER:-wooo}"
|
|
SERVICE_NAME="${SERVICE_NAME:-gitea-act-runner-host.service}"
|
|
SHUTDOWN_TIMEOUT="${SHUTDOWN_TIMEOUT:-1h}"
|
|
LEGACY_RUNNER_STOP_TIMEOUT_SECONDS="${LEGACY_RUNNER_STOP_TIMEOUT_SECONDS:-3700}"
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
SYSTEM_SERVICE_SRC="${SCRIPT_DIR}/gitea-act-runner-host.service"
|
|
USER_SERVICE_SRC="${SCRIPT_DIR}/gitea-act-runner-host.user.service"
|
|
CONFIG_FILE="${RUNNER_DIR}/config.yaml"
|
|
|
|
gitea_task_containers_running() {
|
|
docker ps --format '{{.Names}}' | grep -q '^GITEA-ACTIONS-TASK-'
|
|
}
|
|
|
|
disable_legacy_docker_runner() {
|
|
if ! docker ps -a --format '{{.Names}}' | grep -qx 'gitea-runner'; then
|
|
return 0
|
|
fi
|
|
|
|
echo "Disabling legacy docker-wrapped gitea-runner container"
|
|
docker update --restart=no gitea-runner >/dev/null 2>&1 || true
|
|
|
|
if gitea_task_containers_running; then
|
|
echo "Active Gitea Actions task containers are running; sending SIGINT to drain gitea-runner" >&2
|
|
docker kill --signal=SIGINT gitea-runner >/dev/null 2>&1 || true
|
|
return 0
|
|
fi
|
|
|
|
docker stop -t "${LEGACY_RUNNER_STOP_TIMEOUT_SECONDS}" gitea-runner >/dev/null 2>&1 || true
|
|
}
|
|
|
|
if [ ! -x "${RUNNER_DIR}/act_runner" ]; then
|
|
echo "act_runner binary not found: ${RUNNER_DIR}/act_runner" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "${CONFIG_FILE}" ]; then
|
|
echo "act_runner config not found: ${CONFIG_FILE}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
python3 - "${CONFIG_FILE}" "${SHUTDOWN_TIMEOUT}" <<'PY'
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
path = Path(sys.argv[1])
|
|
shutdown_timeout = sys.argv[2]
|
|
lines = path.read_text().splitlines()
|
|
|
|
in_runner = False
|
|
runner_indent = None
|
|
insert_at = None
|
|
found = False
|
|
updated = []
|
|
|
|
for idx, line in enumerate(lines):
|
|
stripped = line.strip()
|
|
if stripped == "runner:":
|
|
in_runner = True
|
|
runner_indent = len(line) - len(line.lstrip())
|
|
insert_at = idx + 1
|
|
updated.append(line)
|
|
continue
|
|
|
|
if in_runner:
|
|
indent = len(line) - len(line.lstrip())
|
|
if stripped and indent <= runner_indent:
|
|
if not found and insert_at is not None:
|
|
updated.insert(insert_at, f" shutdown_timeout: {shutdown_timeout}")
|
|
found = True
|
|
in_runner = False
|
|
elif stripped.startswith("shutdown_timeout:"):
|
|
updated.append(f" shutdown_timeout: {shutdown_timeout}")
|
|
found = True
|
|
continue
|
|
elif stripped.startswith("timeout:") or stripped.startswith("capacity:"):
|
|
insert_at = len(updated) + 1
|
|
|
|
updated.append(line)
|
|
|
|
if in_runner and not found and insert_at is not None:
|
|
updated.insert(insert_at, f" shutdown_timeout: {shutdown_timeout}")
|
|
found = True
|
|
|
|
if not found:
|
|
raise SystemExit("runner section not found in config")
|
|
|
|
path.write_text("\n".join(updated) + "\n")
|
|
PY
|
|
|
|
disable_legacy_docker_runner
|
|
|
|
install_system_service() {
|
|
sudo install -o root -g root -m 0644 "${SYSTEM_SERVICE_SRC}" "/etc/systemd/system/${SERVICE_NAME}"
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable "${SERVICE_NAME}" >/dev/null
|
|
}
|
|
|
|
install_user_service() {
|
|
local user_service_dir="${HOME}/.config/systemd/user"
|
|
mkdir -p "${user_service_dir}"
|
|
install -m 0644 "${USER_SERVICE_SRC}" "${user_service_dir}/${SERVICE_NAME}"
|
|
systemctl --user daemon-reload
|
|
systemctl --user enable "${SERVICE_NAME}" >/dev/null
|
|
}
|
|
|
|
stop_existing_runner() {
|
|
if pgrep -u "${RUNNER_USER}" -f "${RUNNER_DIR}/act_runner daemon" >/dev/null; then
|
|
pkill -INT -u "${RUNNER_USER}" -f "${RUNNER_DIR}/act_runner daemon" || true
|
|
for _ in $(seq 1 60); do
|
|
pgrep -u "${RUNNER_USER}" -f "${RUNNER_DIR}/act_runner daemon" >/dev/null || return 0
|
|
sleep 1
|
|
done
|
|
echo "Existing act_runner daemon did not stop within 60s" >&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
if sudo -n true >/dev/null 2>&1; then
|
|
SERVICE_SCOPE="system"
|
|
install_system_service
|
|
else
|
|
SERVICE_SCOPE="user"
|
|
install_user_service
|
|
fi
|
|
|
|
if [ "${RESTART_NOW:-0}" = "1" ]; then
|
|
if gitea_task_containers_running; then
|
|
echo "Refusing to restart: Gitea Actions task containers are running" >&2
|
|
exit 1
|
|
fi
|
|
stop_existing_runner
|
|
if [ "${SERVICE_SCOPE}" = "system" ]; then
|
|
sudo systemctl restart "${SERVICE_NAME}"
|
|
else
|
|
systemctl --user restart "${SERVICE_NAME}"
|
|
fi
|
|
elif pgrep -u "${RUNNER_USER}" -f "${RUNNER_DIR}/act_runner daemon" >/dev/null; then
|
|
echo "Existing act_runner daemon is still running; service will take over after the next safe restart."
|
|
else
|
|
if [ "${SERVICE_SCOPE}" = "system" ]; then
|
|
sudo systemctl start "${SERVICE_NAME}"
|
|
else
|
|
systemctl --user start "${SERVICE_NAME}"
|
|
fi
|
|
fi
|
|
|
|
if [ "${SERVICE_SCOPE}" = "system" ]; then
|
|
sudo systemctl --no-pager --full status "${SERVICE_NAME}" | sed -n '1,18p' || true
|
|
else
|
|
systemctl --user --no-pager --full status "${SERVICE_NAME}" | sed -n '1,18p' || true
|
|
fi
|
|
grep -n 'shutdown_timeout' "${CONFIG_FILE}"
|