diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/Dockerfile b/images/actions-runner/v2.328.0-ubuntu-22.04-0/Dockerfile new file mode 100644 index 0000000..8bc6525 --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/Dockerfile @@ -0,0 +1,116 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright 2020 The actions-runner-controller authors. +# SPDX-FileCopyrightText: 2025 k0s authors + +FROM docker.io/library/ubuntu:22.04 + +ARG TARGETPLATFORM +ARG RUNNER_VERSION=2.328.0 +ARG RUNNER_CONTAINER_HOOKS_VERSION=0.7.0 +# Docker and Docker Compose arguments +ARG CHANNEL=stable +ARG DOCKER_VERSION=24.0.7 +ARG DOCKER_COMPOSE_VERSION=v2.23.0 +ARG RUNNER_USER_UID=1001 +ARG DOCKER_GROUP_GID=121 + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update -y \ + && apt-get install -y software-properties-common \ + && add-apt-repository -y ppa:git-core/ppa \ + && apt-get update -y \ + && apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + curl \ + dumb-init \ + git \ + jq \ + openssh-client \ + sudo \ + unzip \ + zip \ + && rm -rf /var/lib/apt/lists/* + +# Download latest git-lfs version +RUN curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash && \ + apt-get install -y --no-install-recommends git-lfs + +RUN adduser --disabled-password --gecos "" --uid $RUNNER_USER_UID runner \ + && groupadd docker --gid $DOCKER_GROUP_GID \ + && usermod -aG sudo runner \ + && usermod -aG docker runner \ + && echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers \ + && echo "Defaults env_keep += \"DEBIAN_FRONTEND\"" >> /etc/sudoers + +ENV HOME=/home/runner + +ENV RUNNER_ASSETS_DIR=/runnertmp +RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ + && if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "x86_64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x64 ; fi \ + && mkdir -p "$RUNNER_ASSETS_DIR" \ + && cd "$RUNNER_ASSETS_DIR" \ + && curl -fLo runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${ARCH}-${RUNNER_VERSION}.tar.gz \ + && tar xzf ./runner.tar.gz \ + && rm runner.tar.gz \ + && ./bin/installdependencies.sh \ + && mv ./externals ./externalstmp \ + # libyaml-dev is required for ruby/setup-ruby action. + # It is installed after installdependencies.sh and before removing /var/lib/apt/lists + # to avoid rerunning apt-update on its own. + && apt-get install -y libyaml-dev \ + && rm -rf /var/lib/apt/lists/* + +ENV RUNNER_TOOL_CACHE=/opt/hostedtoolcache +RUN mkdir /opt/hostedtoolcache \ + && chgrp docker /opt/hostedtoolcache \ + && chmod g+rwx /opt/hostedtoolcache + +RUN cd "$RUNNER_ASSETS_DIR" \ + && curl -fLo runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v${RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${RUNNER_CONTAINER_HOOKS_VERSION}.zip \ + && unzip ./runner-container-hooks.zip -d ./k8s \ + && rm -f runner-container-hooks.zip + +RUN set -vx; \ + export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ + && if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \ + && if [ "$ARCH" = "arm" ]; then export ARCH=armhf ; fi \ + && if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \ + && curl -fLo docker.tgz https://download.docker.com/linux/static/${CHANNEL}/${ARCH}/docker-${DOCKER_VERSION}.tgz \ + && tar zxvf docker.tgz \ + && install -o root -g root -m 755 docker/docker /usr/bin/docker \ + && rm -rf docker docker.tgz + +RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ + && if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \ + && if [ "$ARCH" = "arm" ]; then export ARCH=armv7 ; fi \ + && if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \ + && mkdir -p /usr/libexec/docker/cli-plugins \ + && curl -fLo /usr/libexec/docker/cli-plugins/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \ + && chmod +x /usr/libexec/docker/cli-plugins/docker-compose \ + && ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/bin/docker-compose \ + && which docker-compose \ + && docker compose version + +# We place the scripts in `/usr/bin` so that users who extend this image can +# override them with scripts of the same name placed in `/usr/local/bin`. +COPY entrypoint.sh startup.sh logger.sh graceful-stop.sh update-status /usr/bin/ + +# Copy the docker shim which propagates the docker MTU to underlying networks +# to replace the docker binary in the PATH. +COPY docker-shim.sh /usr/local/bin/docker + +# Configure hooks folder structure. +COPY hooks /etc/arc/hooks/ + +# Add the Python "User Script Directory" to the PATH +ENV PATH="${PATH}:${HOME}/.local/bin/" +ENV ImageOS=ubuntu22 + +RUN echo "PATH=${PATH}" > /etc/environment \ + && echo "ImageOS=${ImageOS}" >> /etc/environment + +USER runner + +ENTRYPOINT ["/bin/bash", "-c"] +CMD ["entrypoint.sh"] diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/README.md b/images/actions-runner/v2.328.0-ubuntu-22.04-0/README.md new file mode 100644 index 0000000..7ebc633 --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/README.md @@ -0,0 +1,15 @@ +# Ubuntu 24.04 GitHub Actions Runner image for k0sproject + +This is a modified version of the official ARC Runner image based on commit +[0e006bb]. The following modifications were made: + +- Can be built for ARMv7. +- Uses `dumb-init` from the APT repositories, so that it can be installed on + 32-bit ARM. +- Add `build-essentials` to obtain a standard build environment. This includes + `make` and enables CGO usage. +- Install `openssh-client` to include the `ssh-keygen` executable. +- Setting the environment variable `DISABLE_RUNNER_DEFAULT_LABELS` allows for + skipping the addition of default labels by the runner. + +[0e006bb]: https://github.com/actions/actions-runner-controller/tree/0e006bb0ff9094e54522cdf89c9bd5ab1806c4af/runner diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/docker-shim.sh b/images/actions-runner/v2.328.0-ubuntu-22.04-0/docker-shim.sh new file mode 100755 index 0000000..21378dd --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/docker-shim.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail + +DOCKER=/usr/bin/docker +if [ ! -e $DOCKER ]; then + DOCKER=/home/runner/bin/docker +fi + +if [[ ${ARC_DOCKER_MTU_PROPAGATION:-false} == true ]] && + (($# >= 2)) && [[ $1 == network && $2 == create ]] && + mtu=$($DOCKER network inspect bridge --format '{{index .Options "com.docker.network.driver.mtu"}}' 2>/dev/null); then + shift 2 + set -- network create --opt com.docker.network.driver.mtu="$mtu" "$@" +fi + +exec $DOCKER "$@" diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/entrypoint.sh b/images/actions-runner/v2.328.0-ubuntu-22.04-0/entrypoint.sh new file mode 100755 index 0000000..c2671b7 --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/entrypoint.sh @@ -0,0 +1,30 @@ +#!/bin/bash +source logger.sh +source graceful-stop.sh +trap graceful_stop TERM + +dumb-init bash <<'SCRIPT' & +source logger.sh + +startup.sh +SCRIPT + +RUNNER_INIT_PID=$! +log.notice "Runner init started with pid $RUNNER_INIT_PID" +wait $RUNNER_INIT_PID +log.notice "Runner init exited. Exiting this process with code 0 so that the container and the pod is GC'ed Kubernetes soon." + +if [ -f /runner/.runner ]; then +# If the runner failed with the following error: +# √ Connected to GitHub +# Failed to create a session. The runner registration has been deleted from the server, please re-configure. +# Runner listener exit with terminated error, stop the service, no retry needed. +# Exiting runner... +# It might have failed to delete the .runner file. +# We use the existence of the .runner file as the indicator that the runner agent has not stopped yet. +# Remove it by ourselves now, so that the dockerd sidecar prestop won't hang waiting for the .runner file to appear. + echo "Removing the .runner file" + rm -f /runner/.runner +fi + +trap - TERM diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/graceful-stop.sh b/images/actions-runner/v2.328.0-ubuntu-22.04-0/graceful-stop.sh new file mode 100644 index 0000000..4f69bbf --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/graceful-stop.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +# This should be shorter enough than the terminationGracePeriodSeconds, +# so that the job is cancelled immediately, instead of hanging for 10 minutes or so and failing without any error message. +RUNNER_GRACEFUL_STOP_TIMEOUT=${RUNNER_GRACEFUL_STOP_TIMEOUT:-15} + +graceful_stop() { + log.notice "Executing actions-runner-controller's SIGTERM handler." + log.notice "Note that if this takes more time than terminationGracePeriodSeconds, the runner will be forcefully terminated by Kubernetes, which may result in the in-progress workflow job, if any, to fail." + + log.notice "Ensuring dockerd is still running." + if ! docker ps -a; then + log.warning "Detected configuration error: dockerd should be running but is already nowhere. This is wrong. Ensure that your init system to NOT pass SIGTERM directly to dockerd!" + fi + + # The below procedure atomically removes the runner from GitHub Actions service, + # to ensure that the runner is not running any job. + # This is required to not terminate the actions runner agent while running the job. + # If we didn't do this atomically, we might end up with a rare race where + # the runner agent is terminated while it was about to start a job. + + # `pushd`` is needed to run the config.sh successfully. + # Without this the author of this script ended up with errors like the below: + # Cannot connect to server, because config files are missing. Skipping removing runner from the server. + # Does not exist. Skipping Removing .credentials + # Does not exist. Skipping Removing .runner + if ! pushd /runner; then + log.error "Failed to pushd ${RUNNER_HOME}" + exit 1 + fi + + # We need to wait for the registration first. + # Otherwise a direct runner pod deletion triggered while the runner entrypoint.sh is about to register itself with + # config.sh can result in this graceful stop process to get skipped. + # In that case, the pod is eventually and forcefully terminated by ARC and K8s, resulting + # in the possible running workflow job after this graceful stop process failed might get cancelled prematurely. + log.notice "Waiting for the runner to register first." + while ! [ -f /runner/.runner ]; do + sleep 1 + done + log.notice "Observed that the runner has been registered." + + if ! /runner/config.sh remove --token "$RUNNER_TOKEN"; then + i=0 + log.notice "Waiting for RUNNER_GRACEFUL_STOP_TIMEOUT=$RUNNER_GRACEFUL_STOP_TIMEOUT seconds until the runner agent to stop by itself." + while [[ $i -lt $RUNNER_GRACEFUL_STOP_TIMEOUT ]]; do + sleep 1 + if ! pgrep Runner.Listener > /dev/null; then + log.notice "The runner agent stopped before RUNNER_GRACEFUL_STOP_TIMEOUT=$RUNNER_GRACEFUL_STOP_TIMEOUT" + break + fi + i=$((i+1)) + done + fi + + if ! popd; then + log.error "Failed to popd from ${RUNNER_HOME}" + exit 1 + fi + + if pgrep Runner.Listener > /dev/null; then + # The below procedure fixes the runner to correctly notify the Actions service for the cancellation of this runner. + # It enables you to see `Error: The operation was canceled.` in the worklow job log, in case a job was still running on this runner when the + # termination is requested. + # + # Note though, due to how Actions work, no all job steps gets `Error: The operation was canceled.` in the job step logs. + # Jobs that were still in the first `Stet up job` step` seem to get `Error: A task was canceled.`, + # + # Anyway, without this, a runer pod is "forcefully" killed by any other controller (like cluster-autoscaler) can result in the workflow job to + # hang for 10 minutes or so. + # After 10 minutes, the Actions UI just shows the failure icon for the step, without `Error: The operation was canceled.`, + # not even showing `Error: The operation was canceled.`, which is confusing. + runner_listener_pid=$(pgrep Runner.Listener) + log.notice "Sending SIGTERM to the actions runner agent ($runner_listener_pid)." + kill -TERM "$runner_listener_pid" + + log.notice "SIGTERM sent. If the runner is still running a job, you'll probably see \"Error: The operation was canceled.\" in its log." + log.notice "Waiting for the actions runner agent to stop." + while pgrep Runner.Listener > /dev/null; do + sleep 1 + done + fi + + # This message is supposed to be output only after the runner agent output: + # 2022-08-27 02:04:37Z: Job test3 completed with result: Canceled + # because this graceful stopping logic is basically intended to let the runner agent have some time + # needed to "Cancel" it. + # At the times we didn't have this logic, the runner agent was even unable to output the Cancelled message hence + # unable to gracefully stop, hence the workflow job hanged like forever. + log.notice "The actions runner process exited." + + if [ "$RUNNER_INIT_PID" != "" ]; then + log.notice "Holding on until runner init (pid $RUNNER_INIT_PID) exits, so that there will hopefully be no zombie processes remaining." + # We don't need to kill -TERM $RUNNER_INIT_PID as the init is supposed to exit by itself once the foreground process(=the runner agent) exists. + wait "$RUNNER_INIT_PID" || : + fi + + log.notice "Graceful stop completed." +} diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-completed.d/update-status b/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-completed.d/update-status new file mode 100755 index 0000000..6efa332 --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-completed.d/update-status @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -u + +exec update-status Idle diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-completed.sh b/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-completed.sh new file mode 100755 index 0000000..9bf775e --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-completed.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# shellcheck source=runner/logger.sh +source logger.sh + +log.debug "Running ARC Job Completed Hooks" + +for hook in /etc/arc/hooks/job-completed.d/*; do + log.debug "Running hook: $hook" + "$hook" "$@" +done diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-started.d/update-status b/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-started.d/update-status new file mode 100755 index 0000000..db7c6fd --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-started.d/update-status @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -u + +exec update-status Running "Run $GITHUB_RUN_ID from $GITHUB_REPOSITORY" diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-started.sh b/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-started.sh new file mode 100644 index 0000000..4b49c22 --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/hooks/job-started.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# shellcheck source=runner/logger.sh +source logger.sh + +log.debug "Running ARC Job Started Hooks" + +for hook in /etc/arc/hooks/job-started.d/*; do + log.debug "Running hook: $hook" + "$hook" "$@" +done diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/logger.sh b/images/actions-runner/v2.328.0-ubuntu-22.04-0/logger.sh new file mode 100755 index 0000000..b80eb91 --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/logger.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# We are not using `set -Eeuo pipefail` here because this file is sourced by +# other scripts that might not be ready for a strict Bash setup. The functions +# in this file do not require it, because they are not handling signals, have +# no external calls that can fail (printf as well as date failures are ignored), +# are not using any variables that need to be set, and are not using any pipes. + +# This logger implementation can be replaced with another logger implementation +# by placing a script called `logger.sh` in `/usr/local/bin` of the image. The +# only requirement for the script is that it defines the following functions: +# +# - `log.debug` +# - `log.notice` +# - `log.warning` +# - `log.error` +# - `log.success` +# +# Each function **MUST** accept an arbitrary amount of arguments that make up +# the (unstructured) logging message. +# +# Additionally the following environment variables **SHOULD** be supported to +# disable their corresponding log entries, the value of the variables **MUST** +# not matter the mere fact that they are set is all that matters: +# +# - `LOG_DEBUG_DISABLED` +# - `LOG_NOTICE_DISABLED` +# - `LOG_WARNING_DISABLED` +# - `LOG_ERROR_DISABLED` +# - `LOG_SUCCESS_DISABLED` + +# The log format is constructed in a way that it can easily be parsed with +# standard tools and simple string manipulations; pattern and example: +# +# YYYY-MM-DD hh:mm:ss.SSS $level --- $message +# 2022-03-19 10:01:23.172 NOTICE --- example message +# +# This function is an implementation detail and **MUST NOT** be called from +# outside this script (which is possible if the file is sourced). +__log() { + local color instant level + + color=${1:?missing required argument} + shift + + level=${FUNCNAME[1]} # `main` if called from top-level + level=${level#log.} # substring after `log.` + level=${level^^} # UPPERCASE + + if [[ ! -v "LOG_${level}_DISABLED" ]]; then + instant=$(date '+%F %T.%-3N' 2>/dev/null || :) + + # https://no-color.org/ + if [[ -v NO_COLOR ]]; then + printf -- '%s %s --- %s\n' "$instant" "$level" "$*" 1>&2 || : + else + printf -- '\033[0;%dm%s %s --- %s\033[0m\n' "$color" "$instant" "$level" "$*" 1>&2 || : + fi + fi +} + +# To log with a dynamic level use standard Bash capabilities: +# +# level=notice +# command || level=error +# "log.$level" message +# +# @formatter:off +log.debug () { __log 37 "$@"; } # white +log.notice () { __log 34 "$@"; } # blue +log.warning () { __log 33 "$@"; } # yellow +log.error () { __log 31 "$@"; } # red +log.success () { __log 32 "$@"; } # green +# @formatter:on diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/startup.sh b/images/actions-runner/v2.328.0-ubuntu-22.04-0/startup.sh new file mode 100755 index 0000000..8bf6b11 --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/startup.sh @@ -0,0 +1,185 @@ +#!/bin/bash +source logger.sh + +RUNNER_ASSETS_DIR=${RUNNER_ASSETS_DIR:-/runnertmp} +RUNNER_HOME=${RUNNER_HOME:-/runner} + +# Let GitHub runner execute these hooks. These environment variables are used by GitHub's Runner as described here +# https://github.com/actions/runner/blob/main/docs/adrs/1751-runner-job-hooks.md +# Scripts referenced in the ACTIONS_RUNNER_HOOK_ environment variables must end in .sh or .ps1 +# for it to become a valid hook script, otherwise GitHub will fail to run the hook +export ACTIONS_RUNNER_HOOK_JOB_STARTED=/etc/arc/hooks/job-started.sh +export ACTIONS_RUNNER_HOOK_JOB_COMPLETED=/etc/arc/hooks/job-completed.sh + +if [ -n "${STARTUP_DELAY_IN_SECONDS}" ]; then + log.notice "Delaying startup by ${STARTUP_DELAY_IN_SECONDS} seconds" + sleep "${STARTUP_DELAY_IN_SECONDS}" +fi + +if [ -z "${GITHUB_URL}" ]; then + log.debug 'Working with public GitHub' + GITHUB_URL="https://github.com/" +else + length=${#GITHUB_URL} + last_char=${GITHUB_URL:length-1:1} + + [[ $last_char != "/" ]] && GITHUB_URL="$GITHUB_URL/"; : + log.debug "Github endpoint URL ${GITHUB_URL}" +fi + +if [ -z "${RUNNER_NAME}" ]; then + log.error 'RUNNER_NAME must be set' + exit 1 +fi + +if [ -n "${RUNNER_ORG}" ] && [ -n "${RUNNER_REPO}" ] && [ -n "${RUNNER_ENTERPRISE}" ]; then + ATTACH="${RUNNER_ORG}/${RUNNER_REPO}" +elif [ -n "${RUNNER_ORG}" ]; then + ATTACH="${RUNNER_ORG}" +elif [ -n "${RUNNER_REPO}" ]; then + ATTACH="${RUNNER_REPO}" +elif [ -n "${RUNNER_ENTERPRISE}" ]; then + ATTACH="enterprises/${RUNNER_ENTERPRISE}" +else + log.error 'At least one of RUNNER_ORG, RUNNER_REPO, or RUNNER_ENTERPRISE must be set' + exit 1 +fi + +if [ -z "${RUNNER_TOKEN}" ]; then + log.error 'RUNNER_TOKEN must be set' + exit 1 +fi + +if [ -z "${RUNNER_REPO}" ] && [ -n "${RUNNER_GROUP}" ];then + RUNNER_GROUPS=${RUNNER_GROUP} +fi + +# Hack due to https://github.com/actions/actions-runner-controller/issues/252#issuecomment-758338483 +if [ ! -d "${RUNNER_HOME}" ]; then + log.error "$RUNNER_HOME should be an emptyDir mount. Please fix the pod spec." + exit 1 +fi + +# if this is not a testing environment +if [[ "${UNITTEST:-}" == '' ]]; then + sudo chown -R runner:docker "$RUNNER_HOME" + # enable dotglob so we can copy a ".env" file to load in env vars as part of the service startup if one is provided + # loading a .env from the root of the service is part of the actions/runner logic + shopt -s dotglob + # use cp instead of mv to avoid issues when src and dst are on different devices + cp -r "$RUNNER_ASSETS_DIR"/* "$RUNNER_HOME"/ + shopt -u dotglob +fi + +if ! cd "${RUNNER_HOME}"; then + log.error "Failed to cd into ${RUNNER_HOME}" + exit 1 +fi + +# past that point, it's all relative pathes from /runner + +config_args=() +if [ "${RUNNER_FEATURE_FLAG_ONCE:-}" != "true" ] && [ "${RUNNER_EPHEMERAL}" == "true" ]; then + config_args+=(--ephemeral) + log.debug 'Passing --ephemeral to config.sh to enable the ephemeral runner.' +fi +if [ "${DISABLE_RUNNER_UPDATE:-}" == "true" ]; then + config_args+=(--disableupdate) + log.debug 'Passing --disableupdate to config.sh to disable automatic runner updates.' +fi +if [ "${DISABLE_RUNNER_DEFAULT_LABELS:-}" == "true" ]; then + config_args+=(--no-default-labels) + log.debug 'Passing --no-default-labels to config.sh to disable default labels.' +fi + + +update-status "Registering" + +retries_left=10 +while [[ ${retries_left} -gt 0 ]]; do + log.debug 'Configuring the runner.' + ./config.sh --unattended --replace \ + --name "${RUNNER_NAME}" \ + --url "${GITHUB_URL}${ATTACH}" \ + --token "${RUNNER_TOKEN}" \ + --runnergroup "${RUNNER_GROUPS}" \ + --labels "${RUNNER_LABELS}" \ + --work "${RUNNER_WORKDIR}" "${config_args[@]}" + + if [ -f .runner ]; then + log.debug 'Runner successfully configured.' + break + fi + + log.debug 'Configuration failed. Retrying' + retries_left=$((retries_left - 1)) + sleep 1 +done + +if [ ! -f .runner ]; then + # we couldn't configure and register the runner; no point continuing + log.error 'Configuration failed!' + exit 2 +fi + +cat .runner +# Note: the `.runner` file's content should be something like the below: +# +# $ cat /runner/.runner +# { +# "agentId": 117, #=> corresponds to the ID of the runner +# "agentName": "THE_RUNNER_POD_NAME", +# "poolId": 1, +# "poolName": "Default", +# "serverUrl": "https://pipelines.actions.githubusercontent.com/SOME_RANDOM_ID", +# "gitHubUrl": "https://github.com/USER/REPO", +# "workFolder": "/some/work/dir" #=> corresponds to Runner.Spec.WorkDir +# } +# +# Especially `agentId` is important, as other than listing all the runners in the repo, +# this is the only change we could get the exact runnner ID which can be useful for further +# GitHub API call like the below. Note that 171 is the agentId seen above. +# curl \ +# -H "Accept: application/vnd.github.v3+json" \ +# -H "Authorization: bearer ${GITHUB_TOKEN}" +# https://api.github.com/repos/USER/REPO/actions/runners/171 + +# Hack due to the DinD volumes +if [ -z "${UNITTEST:-}" ] && [ -e ./externalstmp ]; then + mkdir -p ./externals + mv ./externalstmp/* ./externals/ +fi + +WAIT_FOR_DOCKER_SECONDS=${WAIT_FOR_DOCKER_SECONDS:-120} +if [[ "${DISABLE_WAIT_FOR_DOCKER}" != "true" ]] && [[ "${DOCKER_ENABLED}" == "true" ]]; then + log.debug 'Docker enabled runner detected and Docker daemon wait is enabled' + log.debug "Waiting until Docker is available or the timeout of ${WAIT_FOR_DOCKER_SECONDS} seconds is reached" + if ! timeout "${WAIT_FOR_DOCKER_SECONDS}s" bash -c 'until docker ps ;do sleep 1; done'; then + log.notice "Docker has not become available within ${WAIT_FOR_DOCKER_SECONDS} seconds. Exiting with status 1." + exit 1 + fi +else + log.notice 'Docker wait check skipped. Either Docker is disabled or the wait is disabled, continuing with entrypoint' +fi + +# Unset entrypoint environment variables so they don't leak into the runner environment +unset RUNNER_NAME RUNNER_REPO RUNNER_TOKEN STARTUP_DELAY_IN_SECONDS DISABLE_WAIT_FOR_DOCKER + +# Docker ignores PAM and thus never loads the system environment variables that +# are meant to be set in every environment of every user. We emulate the PAM +# behavior by reading the environment variables without interpreting them. +# +# https://github.com/actions/actions-runner-controller/issues/1135 +# https://github.com/actions/runner/issues/1703 + +# /etc/environment may not exist when running unit tests depending on the platform being used +# (e.g. Mac OS) so we just skip the mapping entirely +if [ -z "${UNITTEST:-}" ]; then + mapfile -t env '" + exit 64 +fi + +if [[ ${RUNNER_STATUS_UPDATE_HOOK:-false} == true ]]; then + + apiserver=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS} + serviceaccount=/var/run/secrets/kubernetes.io/serviceaccount + namespace=$(cat ${serviceaccount}/namespace) + token=$(cat ${serviceaccount}/token) + phase=$1 + message=${2:-} + + data=$(jq -n --arg phase "$phase" \ + --arg message "$message" \ + --arg workflow_repository "${GITHUB_REPOSITORY:-}" \ + --arg workflow_repository_owner "${GITHUB_REPOSITORY_OWNER:-}" \ + --arg workflow_name "${GITHUB_WORKFLOW:-}" \ + --arg workflow_run_id "${GITHUB_RUN_ID:-}" \ + --arg workflow_run_number "${GITHUB_RUN_NUMBER:-}" \ + --arg workflow_job "${GITHUB_JOB:-}" \ + --arg workflow_action "${GITHUB_ACTION:-}" \ + ' + .status.phase = $phase + | .status.message = $message + | .status.workflow.name = $workflow_name + | .status.workflow.runID = $workflow_run_id + | .status.workflow.runNumber = $workflow_run_number + | .status.workflow.repository = $workflow_repository + | .status.workflow.repositoryOwner = $workflow_repository_owner + | .status.workflow.job = $workflow_job + | .status.workflow.action = $workflow_action + ') + + echo "$data" | curl \ + --cacert ${serviceaccount}/ca.crt \ + --data @- \ + --noproxy '*' \ + --header "Content-Type: application/merge-patch+json" \ + --header "Authorization: Bearer ${token}" \ + --show-error \ + --silent \ + --request PATCH \ + "${apiserver}/apis/actions.summerwind.dev/v1alpha1/namespaces/${namespace}/runners/${HOSTNAME}/status" \ + 1>/dev/null +fi diff --git a/images/actions-runner/v2.328.0-ubuntu-22.04-0/wait.sh b/images/actions-runner/v2.328.0-ubuntu-22.04-0/wait.sh new file mode 100644 index 0000000..d8ce918 --- /dev/null +++ b/images/actions-runner/v2.328.0-ubuntu-22.04-0/wait.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +function wait_for_process () { + local max_time_wait=30 + local process_name="$1" + local waited_sec=0 + while ! pgrep "$process_name" >/dev/null && ((waited_sec < max_time_wait)); do + log.debug "Process $process_name is not running yet. Retrying in 1 seconds" + log.debug "Waited $waited_sec seconds of $max_time_wait seconds" + sleep 1 + ((waited_sec=waited_sec+1)) + if ((waited_sec >= max_time_wait)); then + return 1 + fi + done + return 0 +}