This commit is contained in:
Timon
2026-03-05 20:37:58 +01:00
parent 50ef6e15cb
commit a36e5aa060
2 changed files with 221 additions and 0 deletions

97
.github/workflows/runner/containerfile vendored Normal file
View File

@@ -0,0 +1,97 @@
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
# System dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
ca-certificates \
cmake \
curl \
git \
jq \
libssl-dev \
lsb-release \
mold \
pkg-config \
sudo \
unzip \
wget \
&& rm -rf /var/lib/apt/lists/*
# Install sccache to /usr/bin (CI expects it there for RUSTC_WRAPPER)
ARG SCCACHE_VERSION=0.9.1
RUN ARCH=$(uname -m) && \
curl -fsSL "https://github.com/mozilla/sccache/releases/download/v${SCCACHE_VERSION}/sccache-v${SCCACHE_VERSION}-${ARCH}-unknown-linux-musl.tar.gz" \
| tar xz --strip-components=1 -C /usr/bin/ "sccache-v${SCCACHE_VERSION}-${ARCH}-unknown-linux-musl/sccache" && \
chmod +x /usr/bin/sccache
# Install Node.js LTS
ARG NODE_MAJOR=22
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - && \
apt-get install -y --no-install-recommends nodejs && \
rm -rf /var/lib/apt/lists/*
# Create runner user
RUN useradd -m -s /bin/bash runner && \
echo "runner ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/runner
# Create cache directories with correct ownership
RUN mkdir -p /var/lib/github-actions/.cache && \
chown -R runner:runner /var/lib/github-actions
USER runner
WORKDIR /home/runner
# Install Rust stable + wasm target
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile default && \
. "$HOME/.cargo/env" && \
rustup target add wasm32-unknown-unknown && \
rustup component add clippy rustfmt
ENV PATH="/home/runner/.cargo/bin:${PATH}"
# Install cargo tools required by the project
# wasm-bindgen-cli is pinned to match the version in Cargo.toml (=0.2.100)
RUN cargo install --locked wasm-bindgen-cli@0.2.100 && \
cargo install --locked wasm-pack && \
cargo install --locked cargo-about
# Environment variables matching CI configuration
ENV RUSTC_WRAPPER=/usr/bin/sccache
ENV CARGO_INCREMENTAL=0
ENV SCCACHE_DIR=/var/lib/github-actions/.cache
# Install GitHub Actions runner
ARG RUNNER_VERSION=2.322.0
RUN ARCH=$(uname -m | sed 's/x86_64/x64/' | sed 's/aarch64/arm64/') && \
curl -fsSL "https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${ARCH}-${RUNNER_VERSION}.tar.gz" \
| tar xz -C /home/runner
# Entrypoint script: configure and start the runner
COPY --chown=runner:runner <<'ENTRYPOINT' /home/runner/entrypoint.sh
#!/usr/bin/env bash
set -euo pipefail
RUNNER_NAME="${RUNNER_NAME:-$(hostname)}"
RUNNER_LABELS="${RUNNER_LABELS:-target/wasm,target/native}"
RUNNER_WORKDIR="${RUNNER_WORKDIR:-/home/runner/_work}"
# Configure the runner if not already configured
if [ ! -f /home/runner/.runner ]; then
/home/runner/config.sh \
--unattended \
--url "${GITHUB_URL}" \
--token "${RUNNER_TOKEN}" \
--name "${RUNNER_NAME}" \
--labels "${RUNNER_LABELS}" \
--work "${RUNNER_WORKDIR}" \
--replace
fi
# Run with automatic cleanup on container stop
exec /home/runner/run.sh
ENTRYPOINT
RUN chmod +x /home/runner/entrypoint.sh
ENTRYPOINT ["/home/runner/entrypoint.sh"]

124
.github/workflows/runner/setup-runners.sh vendored Executable file
View File

@@ -0,0 +1,124 @@
#!/usr/bin/env bash
set -euo pipefail
IMAGE_NAME="graphite-github-actions-runner"
GITHUB_URL="https://github.com/GraphiteEditor/Graphite"
usage() {
cat <<EOF
Usage: $0 [options]
Spawn self-hosted GitHub Actions runners for Graphite.
Required:
-t TOKEN GitHub runner registration token
-p PREFIX Runner name prefix
Optional:
-n COUNT Number of target/native runners to create (default: 1)
-w COUNT Number of target/wasm runners to create (default: 1)
-u URL GitHub repository URL (default: $GITHUB_URL)
-i IMAGE Container image name (default: $IMAGE_NAME)
-b Build the image before starting runners
-d Tear down existing runners matching the prefix first
-h Show this help message
EOF
exit 1
}
NATIVE_COUNT=1
WASM_COUNT=1
TOKEN=""
PREFIX=""
BUILD=false
TEARDOWN=false
while getopts "t:p:n:w:u:i:bdh" opt; do
case $opt in
t) TOKEN="$OPTARG" ;;
p) PREFIX="$OPTARG" ;;
n) NATIVE_COUNT="$OPTARG" ;;
w) WASM_COUNT="$OPTARG" ;;
u) GITHUB_URL="$OPTARG" ;;
i) IMAGE_NAME="$OPTARG" ;;
b) BUILD=true ;;
d) TEARDOWN=true ;;
h) usage ;;
*) usage ;;
esac
done
if [ -z "$PREFIX" ]; then
echo "Error: -p PREFIX is required"
usage
fi
teardown() {
local pattern="$IMAGE_NAME-${PREFIX}-"
echo "Tearing down containers matching: ${pattern}*"
for cid in $(podman ps -a --filter "name=${pattern}" --format '{{.ID}}' 2>/dev/null); do
name=$(podman inspect --format '{{.Name}}' "$cid")
echo " Stopping and removing $name"
podman rm -f "$cid"
done
}
if [ "$TEARDOWN" = true ]; then
teardown
if [ -z "$TOKEN" ]; then
echo "Teardown complete."
exit 0
fi
fi
if [ -z "$TOKEN" ]; then
echo "Error: -t TOKEN is required to create runners"
usage
fi
if [ "$BUILD" = true ]; then
echo "Building image: $IMAGE_NAME"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
podman build -t "$IMAGE_NAME" -f "$SCRIPT_DIR/containerfile" "$SCRIPT_DIR/.."
echo ""
fi
start_runner() {
local target="$1" # native or wasm
local index="$2"
local name="${IMAGE_NAME}-${PREFIX}-${target}-${index}"
local runner_name="${PREFIX}-${target}-${index}"
local label="target/${target}"
# Each runner gets its own sccache volume for isolation
local cache_vol="${name}-cache"
echo "Starting runner: $name (label: $label)"
podman run -d \
--name "$name" \
--restart unless-stopped \
-v "${cache_vol}:/var/lib/github-actions/.cache" \
-e RUNNER_NAME="$runner_name" \
-e RUNNER_LABELS="$label" \
-e GITHUB_URL="$GITHUB_URL" \
-e RUNNER_TOKEN="$TOKEN" \
"$IMAGE_NAME"
echo " -> $name started (volume: $cache_vol)"
}
echo "Creating $NATIVE_COUNT native runner(s) and $WASM_COUNT wasm runner(s)"
echo ""
for i in $(seq 0 $((NATIVE_COUNT - 1))); do
start_runner "native" "$i"
done
for i in $(seq 0 $((WASM_COUNT - 1))); do
start_runner "wasm" "$i"
done
echo ""
echo "All runners started. Verify with: podman ps --filter name=$IMAGE_NAME"