1
0
Fork 0
mirror of https://code.forgejo.org/forgejo/runner.git synced 2025-08-16 18:01:34 +00:00
forgejo-runner/examples/lxc-systemd/forgejo-runner-service.sh

395 lines
10 KiB
Bash
Raw Normal View History

#!/bin/bash
# Copyright Forgejo Authors.
# SPDX-License-Identifier: MIT
set -o pipefail
: ${TMPDIR:=$(mktemp -d)}
export -n TMPDIR
if ! test -d "$TMPDIR"; then
echo "TMPDIR=$TMPDIR is expected to be a directory"
exit 1
fi
trap "rm -fr $TMPDIR" EXIT
: ${INPUTS_LXC_CONFIG:=docker libvirt lxc}
: ${INPUTS_SERIAL:=}
: ${INPUTS_TOKEN:=}
: ${INPUTS_FORGEJO:=https://code.forgejo.org}
: ${INPUTS_LIFETIME:=7d}
DEFAULT_LXC_HELPERS_VERSION=1.0.3 # renovate: datasource=forgejo-tags depName=forgejo/lxc-helpers
: ${INPUTS_LXC_HELPERS_VERSION:=$DEFAULT_LXC_HELPERS_VERSION}
Update dependency forgejo/runner to v9.0.3 (#812) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [forgejo/runner](https://code.forgejo.org/forgejo/runner) | patch | `9.0.2` -> `9.0.3` | --- ### Release Notes <details> <summary>forgejo/runner (forgejo/runner)</summary> ### [`v9.0.3`](https://code.forgejo.org/forgejo/runner/releases/tag/v9.0.3) [Compare Source](https://code.forgejo.org/forgejo/runner/compare/v9.0.2...v9.0.3) - [User guide](https://forgejo.org/docs/next/user/actions/overview/) - [Administrator guide](https://forgejo.org/docs/next/admin/actions/) - [Container images](https://code.forgejo.org/forgejo/-/packages/container/runner/versions) Release Notes *** <!--start release-notes-assistant--> <!--URL:https://code.forgejo.org/forgejo/runner--> - features - [PR](https://code.forgejo.org/forgejo/runner/pulls/804): <!--number 804 --><!--line 0 --><!--description ZmVhdDogbHhjLXN5c3RlbWQgZGVmYXVsdHMgdG8gdXNpbmcgRm9yZ2VqbyBydW5uZXIgOS4wLjI=-->feat: lxc-systemd defaults to using Forgejo runner 9.0.2<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/784): <!--number 784 --><!--line 0 --><!--description ZmVhdDogLS1oZWFsdGgtKiBvcHRpb25zIGFyZSBhbGxvd2VkIGluIGpvYi48aWQ+LnNlcnZpY2VzLjxpZD4ub3B0aW9ucw==-->feat: --health-\* options are allowed in `job.<id>.services.<id>.options`<!--description--> - bug fixes - [PR](https://code.forgejo.org/forgejo/runner/pulls/810): <!--number 810 --><!--line 0 --><!--description Zml4OiBsb2cgdGhlIFVSTCBvZiB0aGUgYWN0aW9uIHdoZW4gaXQgZmFpbHMgc2NoZW1hIHZhbGlkYXRpb24=-->fix: log the URL of the action when it fails schema validation<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/798): <!--number 798 --><!--line 0 --><!--description Zml4OiBsaW5nZXJpbmcgc2VydmljZXMvdm9sdW1lcy9uZXR3b3JrcyBhZnRlciBqb2JzIGlmIGNsZWFudXAgdGFrZXMgPjFtaW4=-->fix: lingering services/volumes/networks after jobs if cleanup takes >1min<!--description--> - other - [PR](https://code.forgejo.org/forgejo/runner/pulls/806): <!--number 806 --><!--line 0 --><!--description Y2hvcmU6IHVwZ3JhZGUgbHhjLWhlbHBlcnM=-->chore: upgrade lxc-helpers<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/627): <!--number 627 --><!--line 0 --><!--description Y2hvcmU6IHRlYWNoIHJlbm92YXRlIGFib3V0IGV4YW1wbGVzL2x4Yy1zeXN0ZW1kL2Zvcmdlam8tcnVubmVyLXNlcnZpY2Uuc2g=-->chore: teach renovate about examples/lxc-systemd/forgejo-runner-service.sh<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/807): <!--number 807 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2NvbnRhaW5lcmQvZXJyZGVmcyB0byB2MQ==-->Update module github.com/containerd/errdefs to v1<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/803): <!--number 803 --><!--line 0 --><!--description Y2hvcmU6IGV4cGxhaW4gdGhhdCBwYXJ0IG9mIHRoZSBzb3VyY2UgaXMgQXBhY2hlIDI=-->chore: explain that part of the source is Apache 2<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/790): <!--number 790 --><!--line 0 --><!--description Y2hvcmUoY2xlYW51cCk6IGRpc3BhdGNoIHdvcmtmbG93cyBhY2NvcmRpbmcgdG8gdGhlIHJvbGUgb2YgdGhlIHJlcG9zaXRvcnk=-->chore(cleanup): dispatch workflows according to the role of the repository<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/797): <!--number 797 --><!--line 0 --><!--description Y2hvcmU6IHVuaWZ5IGZvcmdlam8gaW1hZ2UgbmFtZXMgbG9jYXRpb24=-->chore: unify forgejo image names location<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/799): <!--number 799 --><!--line 0 --><!--description Y2hvcmU6IHJlcGxhY2UgZG9ja2VyIGh1YiB3aXRoIGNvZGUuZm9yZ2Vqby5vcmc=-->chore: replace docker hub with code.forgejo.org<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/802): <!--number 802 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuMy4x-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.3.1<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/801): <!--number 801 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL29wZW5jb250YWluZXJzL3NlbGludXggdG8gdjEuMTIuMA==-->Update module github.com/opencontainers/selinux to v1.12.0<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/800): <!--number 800 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLWdpdC9nby1naXQvdjUgdG8gdjUuMTYuMg==-->Update module github.com/go-git/go-git/v5 to v5.16.2<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/796): <!--number 796 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2RvY2tlci9jbGkgdG8gdjI4LjMuMytpbmNvbXBhdGlibGU=-->Update module github.com/docker/cli to v28.3.3+incompatible<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/795): <!--number 795 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9yZWxlYXNlLW5vdGVzLWFzc2lzdGFudCB0byB2MS40LjA=-->Update dependency forgejo/release-notes-assistant to v1.4.0<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/794): <!--number 794 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3NwZjEzL3BmbGFnIHRvIHYxLjAuNw==-->Update module github.com/spf13/pflag to v1.0.7<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/793): <!--number 793 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL29wZW5jb250YWluZXJzL2ltYWdlLXNwZWMgdG8gdjEuMS4x-->Update module github.com/opencontainers/image-spec to v1.1.1<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/792): <!--number 792 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnby5ldGNkLmlvL2Jib2x0IHRvIHYxLjQuMg==-->Update module go.etcd.io/bbolt to v1.4.2<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/791): <!--number 791 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3JoeXNkL2FjdGlvbmxpbnQgdG8gdjEuNy43-->Update module github.com/rhysd/actionlint to v1.7.7<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/787): <!--number 787 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLWdpdC9nby1iaWxseS92NSB0byB2NS42LjI=-->Update module github.com/go-git/go-billy/v5 to v5.6.2<!--description--> - [PR](https://code.forgejo.org/forgejo/runner/pulls/789): <!--number 789 --><!--line 0 --><!--description Y2hvcmU6IHRoZSByZWxlYXNlIGxpbmsgdG8gUkVMRUFTRS1OT1RFUy5tZCBpcyBubyBsb25nZXIgbmVlZGVkICh0YWtlIDIp-->chore: the release link to RELEASE-NOTES.md is no longer needed (take 2)<!--description--> <!--end release-notes-assistant--> </details> --- ### Configuration 📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/812 Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org> Co-authored-by: Renovate Bot <bot@kriese.eu> Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-08-06 13:07:24 +00:00
DEFAULT_RUNNER_VERSION=9.0.3 # renovate: datasource=forgejo-releases depName=forgejo/runner
: ${INPUTS_RUNNER_VERSION:=$DEFAULT_RUNNER_VERSION}
: ${KILL_AFTER:=21600} # 6h == 21600
NODEJS_VERSION=20
DEBIAN_RELEASE=bookworm
YQ_VERSION=v4.45.1
SELF=${BASH_SOURCE[0]}
SELF_FILENAME=$(basename "$SELF")
SELF_INSTALLED=/usr/local/bin/$SELF_FILENAME
ETC=/etc/forgejo-runner
LIB=/var/lib/forgejo-runner
LOG=/var/log/forgejo-runner
LOCK=/var/lock/forgejo-runner
: ${HOST:=$(hostname)}
LXC_IPV4_PREFIX="10.105.7"
LXC_IPV6_PREFIX="fd91"
LXC_USER_NAME=debian
LXC_USER_ID=1000
if ${VERBOSE:-false}; then
set -ex
PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}: '
# export LXC_VERBOSE=true # use with caution, it will block .forgejo/workflows/example-lxc-systemd.yml
else
set -e
fi
if test $(id -u) != 0; then
SUDO=sudo
fi
function config_inotify() {
if grep --quiet fs.inotify.max_user_instances=8192 /etc/sysctl.conf; then
return
fi
echo fs.inotify.max_user_instances=8192 | $SUDO tee -a /etc/sysctl.conf
$SUDO sysctl -p
}
function install_or_update_lxc_helpers() {
for lxc_helper in lxc-helpers.sh lxc-helpers-lib.sh; do
local new=$TMPDIR/$lxc_helper
local existing=/usr/local/bin/$lxc_helper
curl --fail -sS -o $new https://code.forgejo.org/forgejo/lxc-helpers/raw/tag/v${INPUTS_LXC_HELPERS_VERSION}/$lxc_helper
if ! test -f $existing || ! cmp --quiet $existing $new; then
if test -f $existing; then
$SUDO mv $existing $existing.backup
fi
$SUDO mv $new $existing
$SUDO chmod +x $existing
fi
done
}
function install_or_update_self() {
if ! cmp --quiet $SELF $SELF_INSTALLED; then
if test -f $SELF_INSTALLED; then
$SUDO mv $SELF_INSTALLED $SELF_INSTALLED.backup
fi
$SUDO cp -a $SELF $SELF_INSTALLED
fi
}
function install_self() {
install_or_update_self
}
function dependencies() {
if ! which curl jq retry >/dev/null; then
export DEBIAN_FRONTEND=noninteractive
$SUDO apt-get update -qq
$SUDO apt-get install -y -qq curl jq retry
fi
if ! which yq >/dev/null; then
$SUDO curl -L --fail -sS -o /usr/local/bin/yq https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_arm64
$SUDO chmod +x /usr/local/bin/yq
fi
install_self
install_or_update_lxc_helpers
if ! which lxc-ls >/dev/null; then
$SUDO lxc-helpers.sh lxc_install_lxc_inside $LXC_IPV4_PREFIX $LXC_IPV6_PREFIX
fi
}
function lxc_name() {
echo runner-${INPUTS_SERIAL}-lxc
}
function lxc_destroy() {
$SUDO lxc-destroy -f $(lxc_name) >/dev/null || true
}
function lxc_create() {
local name=$(lxc_name)
local lib=$LIB/$name
local etc=$ETC/$INPUTS_SERIAL
lxc-helpers.sh --config "$INPUTS_LXC_CONFIG" lxc_container_create $name
echo "lxc.start.auto = 1" | sudo tee -a /var/lib/lxc/$name/config
local bin=/var/lib/lxc/$name/rootfs/usr/local/bin
$SUDO cp -a $SELF $bin/$SELF_FILENAME
$SUDO cp -a /usr/local/bin/forgejo-runner-$INPUTS_RUNNER_VERSION $bin/forgejo-runner
$SUDO cp -a /usr/local/bin/yq $bin/yq
$SUDO cp -a $(which jq) $bin/jq
$SUDO mkdir -p $lib/.cache/actcache
$SUDO chown -R $LXC_USER_ID $lib
lxc-helpers.sh lxc_container_mount $name $lib/.cache/actcache
$SUDO mkdir -p $etc
$SUDO chown -R $LXC_USER_ID $etc
lxc-helpers.sh lxc_container_mount $name $etc
lxc-helpers.sh lxc_container_start $name
if echo $INPUTS_LXC_CONFIG | grep --quiet 'docker'; then
lxc-helpers.sh lxc_install_docker $name
fi
if echo $INPUTS_LXC_CONFIG | grep --quiet 'lxc'; then
local ipv4="10.48.$INPUTS_SERIAL"
local ipv6="fd$INPUTS_SERIAL"
lxc-helpers.sh lxc_install_lxc $name $ipv4 $ipv6
fi
lxc-helpers.sh lxc_container_user_install $name $LXC_USER_ID $LXC_USER_NAME
}
function service_create() {
cat >$TMPDIR/forgejo-runner@.service <<EOF
[Unit]
Description=Forgejo runner %i
After=syslog.target
After=network.target
[Service]
Restart=on-success
ExecStart=/usr/local/bin/${SELF_FILENAME} run_in_copy start
ExecStop=/usr/local/bin/${SELF_FILENAME} stop
TimeoutStopSec=10800
EnvironmentFile=/etc/forgejo-runner/%i/env
[Install]
WantedBy=multi-user.target
EOF
local service=/etc/systemd/system/forgejo-runner@.service
if test -f $service && cmp $TMPDIR/forgejo-runner@.service $service; then
return
fi
$SUDO mkdir -p $ETC
$SUDO chown -R $LXC_USER_ID $ETC
$SUDO mkdir -p $LOG
$SUDO chown -R $LXC_USER_ID $LOG
$SUDO cp $TMPDIR/forgejo-runner@.service $service
$SUDO systemctl daemon-reload
}
function inside() {
local name=$(lxc_name)
# all exported variables must be --unset before running the daemon
lxc-helpers.sh lxc_container_run $name -- sudo --user $LXC_USER_NAME \
INPUTS_SERIAL="$INPUTS_SERIAL" \
INPUTS_LXC_CONFIG="$INPUTS_LXC_CONFIG" \
INPUTS_TOKEN="$INPUTS_TOKEN" \
INPUTS_FORGEJO="$INPUTS_FORGEJO" \
INPUTS_LIFETIME="$INPUTS_LIFETIME" \
KILL_AFTER="$KILL_AFTER" \
VERBOSE="$VERBOSE" \
HOST="$HOST" \
$SELF_FILENAME "$@"
}
function display_default_runner_version() {
echo "Forgejo runner $INPUTS_RUNNER_VERSION"
}
function install_runner() {
local runner=/usr/local/bin/forgejo-runner-$INPUTS_RUNNER_VERSION
if test -f $runner; then
return
fi
$SUDO curl --fail -sS -o $runner https://code.forgejo.org/forgejo/runner/releases/download/v$INPUTS_RUNNER_VERSION/forgejo-runner-$INPUTS_RUNNER_VERSION-linux-amd64
$SUDO chmod +x $runner
}
function ensure_configuration() {
if test -z "$INPUTS_SERIAL"; then
echo "the INPUTS_SERIAL environment variable is not set"
return 1
fi
local etc=$ETC/$INPUTS_SERIAL
$SUDO mkdir -p $etc
if test -f $etc/config; then
INPUTS_LXC_CONFIG=$(cat $etc/config)
else
echo $INPUTS_LXC_CONFIG >$etc/config
fi
$SUDO mkdir -p $LIB/$(lxc_name)/.cache/actcache
}
function ensure_configuration_and_registration() {
local etc=$ETC/$INPUTS_SERIAL
if ! test -f $etc/config.yml; then
forgejo-runner generate-config >$etc/config.yml
cat >$TMPDIR/edit-config <<EOF
.runner.labels = ["docker:docker://data.forgejo.org/oci/node:${NODEJS_VERSION}-${DEBIAN_RELEASE}","lxc:lxc://debian:${DEBIAN_RELEASE}"]
EOF
yq --inplace --from-file $TMPDIR/edit-config $etc/config.yml
cat >$TMPDIR/edit-config <<EOF
.cache.dir = "/var/lib/forgejo-runner/runner-${INPUTS_SERIAL}-lxc/.cache/actcache"
EOF
yq --inplace --from-file $TMPDIR/edit-config $etc/config.yml
fi
if ! test -f $etc/env; then
cat >$etc/env <<EOF
INPUTS_LXC_CONFIG=$INPUTS_LXC_CONFIG
INPUTS_SERIAL=$INPUTS_SERIAL
INPUTS_LIFETIME=$INPUTS_LIFETIME
INPUTS_FORGEJO=$INPUTS_FORGEJO
EOF
fi
if test -f $etc/.runner; then
return
fi
if test -z "$INPUTS_TOKEN"; then
echo "the INPUTS_TOKEN environment variable is not set"
return 1
fi
(
cd $etc
forgejo-runner register --config config.yml --no-interactive \
--token "$INPUTS_TOKEN" \
--name "$HOST-$INPUTS_SERIAL" \
--instance $INPUTS_FORGEJO
)
}
function daemon() {
cd $ETC/$INPUTS_SERIAL
rm -f stopped-* killed-*
touch started-running
set +e
timeout --signal=SIGINT --kill-after=$KILL_AFTER $INPUTS_LIFETIME env \
--unset INPUTS_SERIAL \
--unset INPUTS_LXC_CONFIG \
--unset INPUTS_TOKEN \
--unset INPUTS_FORGEJO \
--unset INPUTS_LIFETIME \
--unset KILL_AFTER \
--unset VERBOSE \
--unset HOST \
/usr/local/bin/forgejo-runner --config config.yml daemon
case $? in
0) touch stopped-gracefully ;;
124) touch stopped-timeout ;;
137) touch stopped-forcefully ;;
esac
set -e
}
function destroy_and_create() {
stop || true
lxc-helpers.sh lxc_container_destroy $(lxc_name)
lxc_create
}
function start() {
# it should be more than
# (time it takes for one runner to be recreated) * (number of runners)
# because they will all start at the same time on boot
local timeout=3600
flock --timeout $timeout $LOCK $SELF destroy_and_create
local log=$LOG/$INPUTS_SERIAL.log
if test -f $log; then
mv $log $log.backup
fi
inside daemon >&$log
}
function kill_runner() {
cd $ETC/$INPUTS_SERIAL
rm -f killed-* started-running
set +e
pkill --exact forgejo-runner
if test $? = 1; then
touch killed-already
return
fi
timeout $KILL_AFTER pidwait --exact forgejo-runner
status=$?
set -e
# pidwait will exit 1 if the process is already gone
# pidwait will exit 0 if the process terminated gracefully before the timeout
if test $status = 0 || test $status = 1; then
touch killed-gracefully
echo "forgejo-runner stopped gracefully"
else
pkill --exact --signal=KILL forgejo-runner
touch killed-forcefully
echo "forgejo-runner stopped forcefully"
fi
}
function stop() {
inside kill_runner
}
function main() {
config_inotify
dependencies
install_runner
service_create
lxc_create
inside ensure_configuration_and_registration
}
function upgrade() {
run_in_copy upgrade_safely "$@"
}
function upgrade_safely() {
local url="$1"
local upgrade_dir=$TMPDIR/upgrades
mkdir -p $TMPDIR/upgrades
local upgrade="$upgrade_dir/$SELF_FILENAME"
curl --fail -sS -o $upgrade $url
chmod +x $upgrade
$upgrade install_runner
$upgrade display_default_runner_version
$upgrade install_or_update_lxc_helpers
$upgrade install_or_update_self
}
#
# ensure an update of the current script does not break a long
# running function (such as `start`) by running from a copy instead
# of the script itself
#
function run_in_copy() {
if test "$#" = 0; then
echo "run_in_copy needs an argument"
return 1
fi
export TMPDIR # otherwise it will not be removed by trap
cp $SELF $TMPDIR/$SELF_FILENAME
exec $TMPDIR/$SELF_FILENAME "$@"
}
"${@:-main}"