mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 18:53:55 +08:00
* chore(ci): parameterize and update GitHub runner version to 2.325.0 * ci: refactor GitHub runner service installation logic Improved service installation workflow by introducing service template creation and cleaning up redundant checks. Enhanced restoration logic with clearer system state assessment and simplified flow for better maintainability.
261 lines
7.4 KiB
Bash
Executable File
261 lines
7.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -e
|
|
|
|
# Default values
|
|
DEFAULT_REPO_URL="https://github.com/sunnypilot"
|
|
START_AT_BOOT=false
|
|
RESTORE_MODE=false
|
|
RUNNER_VERSION="2.325.0"
|
|
|
|
# Parse command line arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--start-at-boot)
|
|
START_AT_BOOT=true
|
|
shift
|
|
;;
|
|
--token)
|
|
GITHUB_TOKEN="$2"
|
|
shift 2
|
|
;;
|
|
--repo)
|
|
REPO_URL="$2"
|
|
shift 2
|
|
;;
|
|
--restore)
|
|
RESTORE_MODE=true
|
|
shift
|
|
;;
|
|
*)
|
|
if [ -z "$GITHUB_TOKEN" ]; then
|
|
GITHUB_TOKEN="$1"
|
|
elif [ -z "$REPO_URL" ]; then
|
|
REPO_URL="$1"
|
|
fi
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Determine BASE_DIR based on mount point
|
|
if mountpoint -q /data/media; then
|
|
BASE_DIR="/data/media/0/github"
|
|
else
|
|
BASE_DIR="/data/github"
|
|
fi
|
|
|
|
# Constants
|
|
RUNNER_USER="github-runner"
|
|
USER_GROUPS="comma,gpu,gpio,sudo"
|
|
RUNNER_DIR="${BASE_DIR}/runner"
|
|
BUILDS_DIR="${BASE_DIR}/builds"
|
|
LOGS_DIR="${BASE_DIR}/logs"
|
|
CACHE_DIR="${BASE_DIR}/cache"
|
|
OPENPILOT_DIR="${BASE_DIR}/openpilot"
|
|
|
|
# Basic utility functions (no dependencies)
|
|
remount_rw() {
|
|
sudo mount -o remount,rw /
|
|
}
|
|
|
|
remount_ro() {
|
|
sync || true # Try to sync but continue even if it fails
|
|
sudo mount -o remount,ro / # Always try to remount as read-only
|
|
}
|
|
|
|
# Always ensure we try to remount as read-only on exit
|
|
trap remount_ro EXIT
|
|
|
|
setup_runner_user() {
|
|
sudo useradd --comment 'GitHub Runner' --create-home --home-dir ${BASE_DIR} ${RUNNER_USER} --shell /bin/bash -G ${USER_GROUPS} || sudo usermod -aG ${USER_GROUPS} ${RUNNER_USER}
|
|
}
|
|
|
|
create_sudoers_entry() {
|
|
sudo grep -qxF "${RUNNER_USER} ALL=(ALL) NOPASSWD: ALL" /etc/sudoers || echo "${RUNNER_USER} ALL=(ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoers
|
|
}
|
|
|
|
set_directory_permissions() {
|
|
sudo chown -R ${RUNNER_USER}:comma "$BASE_DIR"
|
|
sudo chmod -R g+rwx "$BASE_DIR"
|
|
sudo find "$BASE_DIR" -type d -exec chmod g+s {} +
|
|
}
|
|
|
|
setup_directories() {
|
|
echo "Creating necessary directories..."
|
|
sudo mkdir -p "$RUNNER_DIR" "$BUILDS_DIR" "$LOGS_DIR" "$CACHE_DIR" "$OPENPILOT_DIR"
|
|
mkdir -p "/data/openpilot"
|
|
sudo chown -R comma:comma "/data/openpilot"
|
|
sync
|
|
}
|
|
|
|
wipe_bash_logout() {
|
|
export BASE_DIR
|
|
sudo -u ${RUNNER_USER} bash -c "touch ${BASE_DIR}/.bash_logout"
|
|
sudo -u ${RUNNER_USER} bash -c "truncate -s 0 '${BASE_DIR}/.bash_logout'"
|
|
}
|
|
|
|
# System configuration functions (depends on basic utility functions)
|
|
setup_system_configs() {
|
|
echo "Setting up system configurations..."
|
|
remount_rw
|
|
setup_runner_user
|
|
create_sudoers_entry
|
|
remount_ro
|
|
set_directory_permissions
|
|
wipe_bash_logout
|
|
}
|
|
|
|
# Runner setup functions
|
|
install_runner() {
|
|
echo "Downloading and setting up runner..."
|
|
cd "$RUNNER_DIR"
|
|
curl -o actions-runner-linux-arm64-${RUNNER_VERSION}.tar.gz -L https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-arm64-${RUNNER_VERSION}.tar.gz
|
|
sudo -u ${RUNNER_USER} tar -xzf ./actions-runner-linux-arm64-${RUNNER_VERSION}.tar.gz
|
|
sudo rm ./actions-runner-linux-arm64-${RUNNER_VERSION}.tar.gz
|
|
sudo chmod +x ./config.sh
|
|
}
|
|
|
|
configure_runner() {
|
|
remount_rw
|
|
echo "Configuring runner..."
|
|
cd "$RUNNER_DIR"
|
|
sudo -u ${RUNNER_USER} ./config.sh --url "$REPO_URL" --token "$GITHUB_TOKEN" --name $(hostname) --runnergroup "tici-tizi" --labels "tici" --work "$BUILDS_DIR" --unattended
|
|
remount_ro
|
|
}
|
|
|
|
create_service_template() {
|
|
echo "Creating service template..."
|
|
cat <<EOL > "$RUNNER_DIR/bin/actions.runner.service.template"
|
|
[Unit]
|
|
Description={{Description}}
|
|
After=network-online.target nss-lookup.target time-sync.target
|
|
Wants=network-online.target nss-lookup.target time-sync.target
|
|
StartLimitInterval=5
|
|
StartLimitBurst=10
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=root
|
|
ExecStart=/usr/bin/unshare -m -- /bin/bash -c 'mount --bind ${OPENPILOT_DIR} /data/openpilot && setpriv --reuid={{User}} --regid={{User}} --init-groups env HOME=${BASE_DIR} USER={{User}} LOGNAME={{User}} MAIL=/var/mail/{{User}} {{RunnerRoot}}/runsvc.sh'
|
|
WorkingDirectory={{RunnerRoot}}
|
|
KillMode=process
|
|
KillSignal=SIGTERM
|
|
TimeoutStopSec=5min
|
|
Restart=always
|
|
RestartSec=120
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
}
|
|
|
|
install_service() {
|
|
local service_name
|
|
if [ -f "${RUNNER_DIR}/.service" ]; then
|
|
service_name=$(cat "${RUNNER_DIR}/.service")
|
|
else
|
|
service_name="actions.runner.sunnypilot.$(uname -n)"
|
|
fi
|
|
|
|
create_service_template
|
|
remount_rw
|
|
local service_path="/etc/systemd/system/${service_name}"
|
|
echo "Installing systemd service..."
|
|
if [ -f "${service_path}" ]; then
|
|
echo "Service ${service_path} found in systemd, we will delete it"
|
|
sudo rm -f "${service_path}"
|
|
fi
|
|
|
|
cd "$RUNNER_DIR"
|
|
sudo ./svc.sh install $RUNNER_USER
|
|
|
|
if [ "$START_AT_BOOT" = false ]; then
|
|
sudo systemctl disable "${service_name}"
|
|
fi
|
|
remount_ro
|
|
}
|
|
|
|
check_restore_prerequisites() {
|
|
local can_restore=false
|
|
local service_name=""
|
|
|
|
# Check if base runner directory exists
|
|
if [ ! -d "${RUNNER_DIR}" ]; then
|
|
echo "ERROR: Runner directory ${RUNNER_DIR} does not exist"
|
|
echo "This directory is required for restore operations"
|
|
exit 1
|
|
fi
|
|
|
|
# First check if we have the required files for restoration
|
|
if [ -f "${RUNNER_DIR}/.credentials" ] && [ -f "${RUNNER_DIR}/.service" ]; then
|
|
can_restore=true
|
|
service_name=$(cat "${RUNNER_DIR}/.service")
|
|
echo "Found required runner configuration files"
|
|
else
|
|
echo "Missing required runner configuration files"
|
|
echo "Required: .credentials and .service files in ${RUNNER_DIR}"
|
|
exit 1
|
|
fi
|
|
|
|
if ! id "${RUNNER_USER}" &>/dev/null; then
|
|
echo "User ${RUNNER_USER} does not exist"
|
|
fi
|
|
|
|
# Only proceed if we can restore AND need to restore
|
|
if [ "$can_restore" = true ]; then
|
|
echo "Restoration is possible"
|
|
return 0
|
|
else
|
|
echo "No restoration possible"
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
perform_restore() {
|
|
echo "Starting runner restoration..."
|
|
setup_directories
|
|
setup_system_configs
|
|
install_service
|
|
echo "Runner restoration completed successfully"
|
|
}
|
|
|
|
perform_install() {
|
|
echo "Starting fresh installation..."
|
|
setup_directories
|
|
setup_system_configs
|
|
install_runner
|
|
set_directory_permissions
|
|
configure_runner
|
|
install_service
|
|
echo "Installation completed successfully"
|
|
}
|
|
|
|
main() {
|
|
if [ "$RESTORE_MODE" = true ]; then
|
|
echo "Running in restore mode - will only restore system configurations..."
|
|
check_restore_prerequisites
|
|
perform_restore
|
|
else
|
|
# Check required arguments for normal installation
|
|
if [ -z "$GITHUB_TOKEN" ]; then
|
|
echo "Usage: $0 [--start-at-boot] [--token <github_token>] [--repo <repository_url>] [--restore]"
|
|
echo "Required argument (except for --restore): github_token"
|
|
echo "Optional arguments:"
|
|
echo " --start-at-boot Enable auto-start at boot (default: false)"
|
|
echo " --repo Repository URL (default: ${DEFAULT_REPO_URL})"
|
|
echo " --restore Restore existing runner configuration"
|
|
exit 1
|
|
fi
|
|
|
|
# Set repository URL if not provided
|
|
REPO_URL="${REPO_URL:-$DEFAULT_REPO_URL}"
|
|
perform_install
|
|
fi
|
|
|
|
echo "Starting runner service..."
|
|
cd "$RUNNER_DIR"
|
|
sudo ./svc.sh start
|
|
}
|
|
|
|
main
|