-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathci-runner-farm.plg
More file actions
171 lines (165 loc) · 8.84 KB
/
Copy pathci-runner-farm.plg
File metadata and controls
171 lines (165 loc) · 8.84 KB
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
<?xml version='1.0' standalone='yes'?>
<!DOCTYPE PLUGIN [
<!ENTITY name "ci-runner-farm">
<!ENTITY author "Lime Technology">
<!ENTITY version "2026.08.06.1344.40-1.9.0">
<!ENTITY pluginVersion "1.9.0">
<!ENTITY releaseTag "v1.9.0">
<!ENTITY pluginURL "https://github.com/unraid/ci-runner-farm/releases/latest/download/ci-runner-farm.plg">
<!ENTITY packageName "ci-runner-farm-2026.08.06.1344.40-1.9.0.tgz">
<!ENTITY packageURL "https://github.com/unraid/ci-runner-farm/releases/download/v1.9.0/ci-runner-farm-2026.08.06.1344.40-1.9.0.tgz">
<!ENTITY packageMD5 "2e9d7e649a921c3e2ad78eb02adb20ea">
<!ENTITY plgdir "/usr/local/emhttp/plugins/&name;">
<!ENTITY cfgdir "/boot/config/plugins/&name;">
]>
<PLUGIN name="&name;"
author="&author;"
version="&version;"
pluginURL="&pluginURL;"
min="6.12.0"
support="https://github.com/unraid/ci-runner-farm/issues"
icon="docker">
<CHANGES>
### &version;
### Features
* add GitLab runner provider ([#44](https://github.com/unraid/ci-runner-farm/issues/44)) ([ae09e32](https://github.com/unraid/ci-runner-farm/commit/ae09e3256a5e5fc1c69ccb524c0bbdb5207a95da))
</CHANGES>
<!-- plugin package: Unraid downloads it to flash and verifies the MD5 -->
<FILE Name="&cfgdir;/&packageName;">
<URL>&packageURL;</URL>
<MD5>&packageMD5;</MD5>
</FILE>
<!-- install (entities are NOT expanded inside CDATA, so use literal paths) -->
<FILE Run="/bin/bash">
<INLINE><![CDATA[
set -e
PLGDIR="/usr/local/emhttp/plugins/ci-runner-farm"
CFGDIR="/boot/config/plugins/ci-runner-farm"
mkdir -p "$CFGDIR" "$PLGDIR"
# Sweep any older package versions off flash, keeping this build's package.
find "$CFGDIR" -maxdepth 1 -name 'ci-runner-farm-*.tgz' ! -name 'ci-runner-farm-2026.08.06.1344.40-1.9.0.tgz' -delete 2>/dev/null || true
# Extract ONLY into the plugin dir; --no-same-owner forces root ownership;
# --no-overwrite-dir leaves existing dir metadata alone. System dirs untouched.
# The .tgz is kept on flash so the on-boot reinstall works without a download.
tar -xzf "$CFGDIR/ci-runner-farm-2026.08.06.1344.40-1.9.0.tgz" --no-same-owner --no-overwrite-dir -C "$PLGDIR"
chown -R root:root "$PLGDIR"
find "$PLGDIR" -type d -exec chmod 0755 {} +
find "$PLGDIR" -type f -exec chmod 0644 {} +
chmod 0755 "$PLGDIR/include/runner-farm.sh"
[ -d "$PLGDIR/nchan" ] && find "$PLGDIR/nchan" -type f -exec chmod 0755 {} +
# Unraid's emhttp_event executes these on Docker service start/stop — must be +x
[ -d "$PLGDIR/event" ] && find "$PLGDIR/event" -type f -exec chmod 0755 {} +
# Config defaults are NOT seeded to flash — the settings page and runner-farm.sh
# both fall back to built-in defaults, so flash only ever holds what the user set.
# Provider-specific editable Dockerfiles keep a GitLab job-image build from
# replacing a customized GitHub runner image (and vice versa). Existing installs
# used the unsuffixed Dockerfile; copy it forward once as the GitHub source while
# retaining the old file as a compatibility/downgrade fallback.
if [ ! -f "$CFGDIR/Dockerfile.github" ]; then
if [ -f "$CFGDIR/Dockerfile" ]; then
cp "$CFGDIR/Dockerfile" "$CFGDIR/Dockerfile.github"
else
cp "$PLGDIR/default.github.Dockerfile" "$CFGDIR/Dockerfile.github"
fi
fi
[ -f "$CFGDIR/Dockerfile.gitlab" ] || cp "$PLGDIR/default.gitlab.Dockerfile" "$CFGDIR/Dockerfile.gitlab"
# Migrate GitHub Dockerfiles seeded before the cache-ownership fix: without
# runner-owned CACHE_MOUNTS destinations baked into the image, Docker's
# bind-mount auto-creation leaves root-owned parents and a non-root runner
# fails writing beside them (rustup: "could not create bin directory
# '/home/runner/.cargo/bin'"). Patch only files that still carry the stock
# packages marker and lack the fix; customized files without the marker get a
# notice instead.
DF="$CFGDIR/Dockerfile.github"
if [ -f "$DF" ] && ! grep -q 'mkdir -p /home/runner/.cargo/registry' "$DF"; then
if grep -q '^# && rm -rf /var/lib/apt/lists/\*' "$DF"; then
BLK=$(mktemp)
cat > "$BLK" <<'EOF_CACHEDIRS'
# Pre-create the default CACHE_MOUNTS destinations as runner-owned. When these
# paths are absent from the image, Docker's bind-mount auto-creation makes the
# missing parent directories root-owned, and a non-root runner (RUN_AS_ROOT=false)
# can then no longer write beside them — e.g. rustup fails with "could not
# create bin directory '/home/runner/.cargo/bin': Permission denied".
RUN mkdir -p /home/runner/.cargo/registry /home/runner/.cargo/git \
/home/runner/.cache/sccache /home/runner/.cache/yarn /home/runner/.cache/ms-playwright \
/home/runner/.npm /home/runner/.local/share/pnpm/store \
&& chown -R runner:runner /home/runner/.cargo /home/runner/.cache /home/runner/.npm /home/runner/.local
EOF_CACHEDIRS
sed -i "\@^# && rm -rf /var/lib/apt/lists/\*@r $BLK" "$DF"
rm -f "$BLK"
echo "ci-runner-farm: patched saved Dockerfile to pre-create runner-owned cache dirs (press Build to rebuild the runner image)."
else
echo "ci-runner-farm: NOTE - saved $DF lacks the runner-owned cache-dir block from default.github.Dockerfile; merge it manually so non-root runners can write beside the cache mounts."
fi
fi
( docker pull myoung34/github-runner:latest >/dev/null 2>&1 & ) || true
( docker pull gitlab/gitlab-runner:alpine >/dev/null 2>&1 & ) || true
# Bring the fleet + autoscaler up. Runs on manual install AND on every boot
# (rc.local reinstalls plugins), detached so it waits for dockerd+array without
# blocking. No-op until the selected provider's runner token is configured.
( nohup "$PLGDIR/include/runner-farm.sh" boot-autostart >>"$CFGDIR/boot.log" 2>&1 & ) || true
echo ""
echo "+=============================================================+"
echo "| ci-runner-farm 2026.08.06.1344.40-1.9.0 installed. "
echo "| Settings > Utilities > CI Runner Farm "
echo "| Select GitHub or GitLab, save its token, then Start. "
echo "+=============================================================+"
]]></INLINE>
</FILE>
<!-- remove -->
<FILE Run="/bin/bash" Method="remove">
<INLINE><![CDATA[
set -euo pipefail
PLGDIR="/usr/local/emhttp/plugins/ci-runner-farm"
CFGDIR="/boot/config/plugins/ci-runner-farm"
ENGINE="$PLGDIR/include/runner-farm.sh"
if [ -x "$ENGINE" ]; then
if ! "$PLGDIR/include/runner-farm.sh" stop >>"$CFGDIR/boot.log" 2>&1; then
echo "ci-runner-farm NOT removed: one or more runners, jobs, or privileged sidecars could not be stopped safely." >&2
echo "Review $CFGDIR/boot.log, retry Stop, or use the separately confirmed local-forget recovery action if GitLab is permanently unreachable." >&2
exit 1
fi
else
# A partially deleted runtime cannot perform the normal ownership-verified
# teardown. Never interpret that as an empty farm: prove through Docker that
# no plugin-labelled manager, validation container, privileged DinD sidecar,
# host-socket executor workload, or registry mirror survives before allowing
# the remaining package files to be removed.
command -v docker >/dev/null 2>&1 || {
echo "ci-runner-farm NOT removed: cleanup engine is missing and Docker is unavailable, so owned runtime resources cannot be enumerated." >&2
echo "Start Docker or restore the plugin runtime, then retry removal." >&2
exit 1
}
owned_runtime=""
for filter in 'label=net.unraid.ci-runner-farm.managed=true' 'label=net.unraid.ci-runner-farm.sidecar=true' 'label=net.unraid.ci-runner-farm.role=mirror'
do
if ! ids=$(docker ps -aq --filter "$filter" 2>/dev/null); then
echo "ci-runner-farm NOT removed: cleanup engine is missing and Docker ownership enumeration failed." >&2
exit 1
fi
[ -z "$ids" ] || owned_runtime="${owned_runtime}${ids} "
done
if ! ids=$(docker ps -aq --filter 'label=com.gitlab.gitlab-runner.managed=true' --filter 'label=net.unraid.ci-runner-farm.provider=gitlab' 2>/dev/null); then
echo "ci-runner-farm NOT removed: cleanup engine is missing and GitLab executor ownership enumeration failed." >&2
exit 1
fi
[ -z "$ids" ] || owned_runtime="${owned_runtime}${ids} "
if [ -n "$owned_runtime" ]; then
echo "ci-runner-farm NOT removed: the cleanup engine is missing while plugin-owned Docker resources still exist." >&2
echo "Restore the plugin runtime, then retry removal so those resources can be stopped safely." >&2
exit 1
fi
fi
if ! rm -rf -- "$PLGDIR" || [ -e "$PLGDIR" ]; then
echo "ci-runner-farm NOT fully removed: failed to delete the installed runtime at $PLGDIR." >&2
exit 1
fi
# The downloaded package is just a cache; drop it. Config + credentials stay.
if ! rm -f -- "$CFGDIR"/ci-runner-farm-*.tgz; then
echo "ci-runner-farm NOT fully removed: runtime cleanup succeeded, but a cached package could not be deleted from $CFGDIR." >&2
exit 1
fi
echo "ci-runner-farm removed. Config + credentials left in /boot/config/plugins/ci-runner-farm (delete manually to purge)."
]]></INLINE>
</FILE>
</PLUGIN>