-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinstall.sh
executable file
·216 lines (182 loc) · 5.72 KB
/
install.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/bin/bash
set -euo pipefail
# shellcheck disable=SC1091
source start.sh
env_file_path() {
local scope="$1"
echo "$PWD/$(service_name "$scope").env"
}
write_envs() {
local env_file=$1
shift
new_keys=()
new_values=()
# Parse input arguments into arrays for keys and values
for arg in "$@"; do
IFS='=' read -r key value <<<"$arg"
new_keys+=("$key")
new_values+=("$value")
done
tmpfile=$(mktemp)
processed_keys=()
# If the file exists, process it line by line
if [[ -f "$env_file" ]]; then
while IFS= read -r line || [[ -n $line ]]; do
# Preserve comments and empty lines
if [[ "$line" =~ ^\s*# ]] || [[ -z "$line" ]]; then
echo "$line" >>"$tmpfile"
continue
fi
# Parse lines into file_key and file_value
IFS='=' read -r file_key file_value <<<"$line"
file_key=$(echo "$file_key" | xargs)
file_value=$(echo "$file_value" | xargs)
# Check if the key exists in new_keys
found=0
for i in "${!new_keys[@]}"; do
if [[ "${new_keys[$i]}" == "$file_key" ]]; then
processed_keys+=("${new_keys[$i]}")
# Update the value as needed
if [[ -z "${new_values[$i]}" ]]; then
# If the new value is empty, retain the original value
echo "$file_key=$file_value" >>"$tmpfile"
else
echo "$file_key=${new_values[$i]}" >>"$tmpfile"
fi
found=1
break
fi
done
# Retain the original line if the key wasn't found in new_keys
if [[ $found -eq 0 ]]; then
if [[ -z $file_value ]]; then
echo "$file_key=" >>"$tmpfile"
else
echo "$file_key=$file_value" >>"$tmpfile"
fi
processed_keys+=("$file_key")
fi
done <"$env_file"
fi
# Append remaining new keys/values that were not in the original file
for i in "${!new_keys[@]}"; do
if [[ ! " ${processed_keys[*]:-} " =~ " ${new_keys[$i]} " ]]; then
if [[ -z "${new_values[$i]}" ]]; then
echo "${new_keys[$i]}=" >>"$tmpfile"
else
echo "${new_keys[$i]}=${new_values[$i]}" >>"$tmpfile"
fi
fi
done
# Replace the original file with the temporary file
mv "$tmpfile" "$env_file"
}
create_systemd_service() {
local scope="$1"
local token="$2"
local labels="$3"
# Check if the systemd directory exists
if [ ! -d "/etc/systemd/system" ]; then
echo "Systemd directory not found"
exit 1
fi
local service=$(service_name "$scope")
local image=$(image_name "$scope")
local env_file=$(env_file_path "$scope")
# Write environment variables for the dockerfile to use
write_envs "$env_file" "RUNNER_NAME=$(hostname)" "RUNNER_URL=https://github.com/$scope" "RUNNER_TOKEN=$token" "RUNNER_LABELS=$labels"
# Find the docker binary
docker="$(which docker || echo "/usr/bin/docker")"
# Create the systemd service file
cat <<EOF | sudo tee "/etc/systemd/system/$service.service" >/dev/null
[Unit]
Description=Self hosted GitHub runner
[Service]
Restart=always
ExecStartPre=-$docker rm -f $service
ExecStart=$docker run --env-file $env_file --rm --name $service $image
ExecStop=$docker stop $service
[Install]
WantedBy=default.target
EOF
# Reload systemd daemon
sudo systemctl daemon-reload
echo "Service $service created and ready to start. Run './start.sh' to start the service."
}
check_and_install_docker() {
local user=$(whoami)
if ! command -v docker &>/dev/null; then
echo "Docker is not installed. Installing Docker..."
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" |
sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Add the current user to the docker group to allow running docker without sudo
sudo usermod -aG docker "$user"
echo "Docker has been installed. You might need to log out and log back in to use Docker without sudo."
else
echo "Docker is already installed."
fi
}
main() {
# Check if the script is being run as root
if [ "$EUID" -eq 0 ]; then
echo "This script must not be run as root or with sudo."
exit 1
fi
# Parse command line arguments
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-t | --token)
token="$2"
shift
;;
-s | --scope)
scope="$2"
shift
;;
-l | --labels)
labels="$2"
shift
;;
*)
echo "Unknown option: $key"
exit 1
;;
esac
shift
done
if [ -z "${scope:-}" ]; then
echo "--scope is required (e.g. 'org' or 'owner/repo')"
exit 1
fi
local env_path=$(env_file_path "$scope")
if [ -f "$env_path" ]; then
source "$env_path"
fi
token="${token:-${RUNNER_TOKEN:-}}"
if [ -z "${token:-}" ]; then
echo "--token is required."
if [[ "$scope" == *"/"* ]]; then
echo "Visit https://github.com/$scope/settings/actions/runners/new?arch=x64&os=linux"
else
echo "Visit https://github.com/organizations/$scope/settings/actions/runners/new?arch=x64&os=linux"
fi
exit 1
fi
check_and_install_docker
create_systemd_service "$scope" "$token" "${labels:-}"
}
# Execute the main function only if the script is called directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi