From 6a3a9bde14730e5a8536728a7a8482eaf5fb905c Mon Sep 17 00:00:00 2001 From: casjay Date: Mon, 3 Aug 2026 11:57:10 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Enable=20shared=20act=5Frunner?= =?UTF-8?q?=20cache-server=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turned on the act_runner Actions cache instead of leaving it disabled. The standalone `cache-server` process was already being launched unconditionally by zz-act_runner.sh but had no `external_secret`, so it was refusing to start (the binary requires a non-empty secret even though its own `cache.enabled` field is unused). Wired a shared, randomly generated secret through the existing REPLACE_* templating pattern so the "gitea" runner, the cache-server, and the extra runner-N daemons spawned by start-runners all share one cache backend. - rootfs/tmp/etc/act_runner/default_config.yaml: cache.enabled: true; added external_server (pointed at the local cache-server) and external_secret placeholders - rootfs/tmp/etc/act_runner/cache_server.yaml: cache.enabled: true; added external_secret placeholder (required for the binary to start) - rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: added __gen_cache_secret() (mirrors __gen_auth_token's persisted-token pattern, stored at $CONF_DIR/tokens/cache_secret); substitutes REPLACE_RUNNER_CACHE_SECRET into both the runner config and the cache-server config; exports RUNNER_CACHE_HOST/PORT/SECRET for start-runners; bumped version stamp - rootfs/usr/local/bin/start-runners: generates a shared runners-cache.yaml from the exported cache env vars and passes --config to both `act_runner register` and `act_runner daemon` for every runner-N instance, so they use the same external cache server instead of an unshared per-process local cache - TODO.AI.md: logged pre-existing script-lint findings (missing `--` before grep queries throughout zz-act_runner.sh, a UUOC in start-runners, an unpinned/stale docker.yaml CI workflow, and forbidden OCI labels in the Dockerfile) surfaced incidentally by the lint pass for this change but out of scope for it --- TODO.AI.md | 17 +++++++++++ rootfs/tmp/etc/act_runner/cache_server.yaml | 3 +- rootfs/tmp/etc/act_runner/default_config.yaml | 4 ++- rootfs/usr/local/bin/start-runners | 21 ++++++++++++-- .../local/etc/docker/init.d/zz-act_runner.sh | 28 ++++++++++++++++++- 5 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 TODO.AI.md diff --git a/TODO.AI.md b/TODO.AI.md new file mode 100644 index 0000000..607f33a --- /dev/null +++ b/TODO.AI.md @@ -0,0 +1,17 @@ +# TODO.AI.md + +## Lint cleanup — pre-existing script-lint violations (found incidentally while wiring act_runner cache-server) + +Not fixed yet — out of scope for the cache-enablement change; flagged by `script-lint` agent. + +- `rootfs/usr/local/bin/start-runners`: + - line 24: UUOC — `echo "$SERVER_ADDRESS" | grep -q '://'` should be `[[ "$SERVER_ADDRESS" == *"://"* ]]` + - line 24: `grep -q '://'` missing `--` before query +- `rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh`: + - line 4: `##@Version` header present but no matching `VERSION=` assignment in script body + - missing `--` before the grep query at lines 124 (x2), 130, 133, 134, 369, 390, 401, 438, 468, 525 (x2), 544 (x2, also should quote the `grep` pattern), 571, 583 + +## Other observations not yet actioned + +- `.gitea/workflows/docker.yaml` uses the same stale/unpinned action pattern (`@v2`-`@v4`, DockerHub-only, `catthehacker/ubuntu:act-latest`) that was removed from the `opengist` repo's duplicate workflow — no `build.yml` counterpart exists here yet. +- `Dockerfile` sets forbidden OCI labels (`org.opencontainers.image.base.name`, `.schema-version`, duplicate `authors`) — same issue previously found and fixed in `opengist`. diff --git a/rootfs/tmp/etc/act_runner/cache_server.yaml b/rootfs/tmp/etc/act_runner/cache_server.yaml index 319af73..6373a26 100644 --- a/rootfs/tmp/etc/act_runner/cache_server.yaml +++ b/rootfs/tmp/etc/act_runner/cache_server.yaml @@ -2,7 +2,8 @@ log: level: warn cache: - enabled: false + enabled: true dir: 'REPLACE_RUNNER_CACHE_DIR' host: '0.0.0.0' port: REPLACE_RUNNER_CACHE_PORT + external_secret: 'REPLACE_RUNNER_CACHE_SECRET' diff --git a/rootfs/tmp/etc/act_runner/default_config.yaml b/rootfs/tmp/etc/act_runner/default_config.yaml index 366f7ab..265db74 100644 --- a/rootfs/tmp/etc/act_runner/default_config.yaml +++ b/rootfs/tmp/etc/act_runner/default_config.yaml @@ -66,4 +66,6 @@ container: docker_host: '' cache: - enabled: false + enabled: true + external_server: 'http://REPLACE_RUNNER_CACHE_HOST:REPLACE_RUNNER_CACHE_PORT/' + external_secret: 'REPLACE_RUNNER_CACHE_SECRET' diff --git a/rootfs/usr/local/bin/start-runners b/rootfs/usr/local/bin/start-runners index 6484010..6c2ac6c 100755 --- a/rootfs/usr/local/bin/start-runners +++ b/rootfs/usr/local/bin/start-runners @@ -47,18 +47,33 @@ __log "Starting $RUNNERS_START act_runner instance(s)" __log "Server Address: $SERVER_ADDRESS" __log "Runner Name Prefix: ${RUNNER_NAME_PREFIX:-runner}" # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# Shared cache config so runner-N instances use the same cache-server +# started by zz-act_runner.sh instead of an unshared per-process cache. +RUNNERS_CACHE_CONFIG="" +if [ -n "$RUNNER_CACHE_HOST" ] && [ -n "$RUNNER_CACHE_PORT" ] && [ -n "$RUNNER_CACHE_SECRET" ]; then + RUNNERS_CACHE_CONFIG="/config/act_runner/runners-cache.yaml" + cat <"$RUNNERS_CACHE_CONFIG" +cache: + enabled: true + external_server: 'http://${RUNNER_CACHE_HOST}:${RUNNER_CACHE_PORT}/' + external_secret: '${RUNNER_CACHE_SECRET}' +EOF +fi +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Register a single runner synchronously (no daemon start) __register_runner() { local runner_id=$1 local runner_name="${RUNNER_NAME_PREFIX:-runner}-${runner_id}" local runner_dir="/config/act_runner/reg/${runner_name}" + local config_args=() mkdir -p "$runner_dir" [ -d "$runner_dir" ] && cd "$runner_dir" || return 1 + [ -n "$RUNNERS_CACHE_CONFIG" ] && config_args=(--config "$RUNNERS_CACHE_CONFIG") if [ ! -f "$runner_dir/.runner" ]; then __log "Registering runner: $runner_name (ID: $runner_id)" - act_runner register --instance "$SERVER_ADDRESS" --token "$SERVER_TOKEN" --name "$runner_name" --labels "$RUNNER_LABELS" --no-interactive + act_runner register "${config_args[@]}" --instance "$SERVER_ADDRESS" --token "$SERVER_TOKEN" --name "$runner_name" --labels "$RUNNER_LABELS" --no-interactive if [ $? -ne 0 ]; then __log "ERROR: Failed to register runner $runner_name" return 1 @@ -72,10 +87,12 @@ __start_runner_daemon() { local runner_id=$1 local runner_name="${RUNNER_NAME_PREFIX:-runner}-${runner_id}" local runner_dir="/config/act_runner/reg/${runner_name}" + local config_args=() [ -d "$runner_dir" ] && cd "$runner_dir" || return 1 + [ -n "$RUNNERS_CACHE_CONFIG" ] && config_args=(--config "$RUNNERS_CACHE_CONFIG") __log "Starting daemon for runner: $runner_name" - exec act_runner daemon + exec act_runner daemon "${config_args[@]}" } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Phase 1: register all runners sequentially so IDs are assigned in order diff --git a/rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh b/rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh index 0cac728..7cd0e63 100755 --- a/rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh +++ b/rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # shellcheck shell=bash # - - - - - - - - - - - - - - - - - - - - - - - - - -##@Version : 202606261600-git +##@Version : 202608031200-git # @@Author : Jason Hempstead # @@Contact : jason@casjaysdev.pro # @@License : LICENSE.md @@ -142,6 +142,26 @@ __gen_auth_token() { return $exitCode } # - - - - - - - - - - - - - - - - - - - - - - - - - +# shared secret between the runner(s) and the standalone cache-server +__gen_cache_secret() { + local secret token_dir exitCode + exitCode=1 + token_dir="$CONF_DIR/tokens" + mkdir -p "$token_dir" >/dev/null 2>&1 + if [ -n "$RUNNER_CACHE_SECRET" ]; then + secret="$RUNNER_CACHE_SECRET" + elif [ -s "$token_dir/cache_secret" ]; then + secret="$(<"$token_dir/cache_secret")" + fi + [ -z "$secret" ] && secret="$(__random_password 32)" + if [ -n "$secret" ]; then + exitCode=0 + echo "$secret" + echo "$secret" >"$token_dir/cache_secret" + fi + return $exitCode +} +# - - - - - - - - - - - - - - - - - - - - - - - - - # Script to execute START_SCRIPT="/usr/local/etc/docker/exec/$SERVICE_NAME" # - - - - - - - - - - - - - - - - - - - - - - - - - @@ -305,6 +325,7 @@ RUNNER_DAEMON_LOG="${RUNNER_DAEMON_LOG:-$LOG_DIR/daemon.log}" RUNNER_CACHE_HOST="${RUNNER_CACHE_HOST:-$IP4_ADDRESS}" CACHE_CONFIG_FILE="${CACHE_CONFIG_FILE:-$CONF_DIR/cache_server.yaml}" CACHE_LOG_FILE="${CACHE_LOG_FILE:-$LOG_DIR/cache.log}" +RUNNER_CACHE_SECRET="${RUNNER_CACHE_SECRET:-}" # - - - - - - - - - - - - - - - - - - - - - - - - - # Additional variables @@ -384,6 +405,7 @@ __run_pre_execute_checks() { [ -d "$DATA_DIR/cache" ] || mkdir -p "$DATA_DIR/cache" [ -d "$CONF_DIR/tokens" ] || mkdir -p "$CONF_DIR/tokens" SYS_AUTH_TOKEN="${SYS_AUTH_TOKEN:-$(__gen_auth_token)}" + RUNNER_CACHE_SECRET="${RUNNER_CACHE_SECRET:-$(__gen_cache_secret)}" if [ -f "$RUNNER_CONFIG_DEFAULT" ]; then mkdir -p "$RUNNER_DEFAULT_HOME" "$TMP_DIR/runners/gitea" [ -f "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" ] || copy "$RUNNER_CONFIG_DEFAULT" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" @@ -392,6 +414,7 @@ __run_pre_execute_checks() { __replace "REPLACE_RUNNER_HOME" "$RUNNER_DEFAULT_HOME" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" __replace "REPLACE_RUNNER_CACHE_HOST" "$RUNNER_CACHE_HOST" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" __replace "REPLACE_RUNNER_CACHE_PORT" "$RUNNER_CACHE_PORT" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" + __replace "REPLACE_RUNNER_CACHE_SECRET" "$RUNNER_CACHE_SECRET" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" if [ ! -f "$RUNNER_DEFAULT_HOME/runners" ] && [ -n "$SYS_AUTH_TOKEN" ]; then echo "creating gitea runner in $RUNNER_DEFAULT_HOME and registering with http://$INSTANCE_HOSTNAME" act_runner register --config "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" --labels "$RUNNER_LABELS" --name "gitea" --instance "http://$RUNNER_IP_ADDRESS:$GITEA_PORT" --token "$SYS_AUTH_TOKEN" --no-interactive >>"$RUNNER_LOG_FILE" 2>&1 & @@ -485,6 +508,8 @@ __post_execute() { local postMessageEnd="Finished post commands for $SERVICE_NAME" export RUNNERS_START="${RUNNERS_START:-5}" RUNNER_LABELS RUNNERS_LOG_DIR="$LOG_DIR" export SERVER_ADDRESS="$RUNNER_IP_ADDRESS:$GITEA_PORT" SERVER_TOKEN="${RUNNER_AUTH_TOKEN:-$SYS_AUTH_TOKEN}" + export RUNNER_CACHE_HOST RUNNER_CACHE_PORT + export RUNNER_CACHE_SECRET="${RUNNER_CACHE_SECRET:-$(__gen_cache_secret)}" # wait sleep $waitTime @@ -512,6 +537,7 @@ __post_execute() { mkdir -p "$DATA_DIR/cache" __replace "REPLACE_RUNNER_CACHE_DIR" "$DATA_DIR/cache" "$CACHE_CONFIG_FILE" __replace "REPLACE_RUNNER_CACHE_PORT" "$RUNNER_CACHE_PORT" "$CACHE_CONFIG_FILE" + __replace "REPLACE_RUNNER_CACHE_SECRET" "$RUNNER_CACHE_SECRET" "$CACHE_CONFIG_FILE" act_runner cache-server --config "$CACHE_CONFIG_FILE" 2>>/dev/stderr >>"$CACHE_LOG_FILE" & execPid=$! sleep 5