Initial dockerfile for github-runner

This commit is contained in:
uazo 2021-07-05 15:48:55 +00:00
parent 4f907dbb53
commit 91c92a47c8
4 changed files with 217 additions and 0 deletions

View File

@ -0,0 +1,51 @@
FROM nestybox/ubuntu-focal-docker
# Extra deps for GHA Runner
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y \
curl \
jq \
sudo \
unzip \
wget \
zip \
git \
&& rm -rf /var/lib/apt/list/*
# Add and config runner user as sudo
RUN useradd -m runner \
&& usermod -aG sudo runner \
&& usermod -aG docker runner \
&& echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers
# Build args
ARG TARGETPLATFORM=x64
ARG RUNNER_VERSION=2.301.0
WORKDIR /runner
# Runner download supports amd64 as x64
RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
&& if [ "$ARCH" = "amd64" ]; then export ARCH=x64 ; fi \
&& curl -Ls -o runner.tar.gz https://github.com/uazo/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 \
&& rm -rf /var/lib/apt/lists/*
# Dumb Init
#RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
# && curl -Ls -o /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.2/dumb-init_1.2.2_${ARCH} \
# && chmod +x /usr/local/bin/dumb-init
COPY startup.sh .
# Add patched scripts from GHA runner (svc.sh and RunnerService.js)
COPY --chown=runner:runner patched/ ./patched/
RUN chmod +x ./patched/runsvc.sh ./startup.sh
USER runner
#ENTRYPOINT ["/usr/local/bin/dumb-init", "--"]
CMD ./startup.sh

View File

@ -0,0 +1,91 @@
#!/usr/bin/env node
// Copyright (c) GitHub. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
var childProcess = require("child_process");
var path = require("path")
var supported = ['linux', 'darwin']
if (supported.indexOf(process.platform) == -1) {
console.log('Unsupported platform: ' + process.platform);
console.log('Supported platforms are: ' + supported.toString());
process.exit(1);
}
var stopping = false;
var listener = null;
var runService = function() {
var listenerExePath = path.join(__dirname, '../bin/Runner.Listener');
var interactive = process.argv[2] === "interactive";
if(!stopping) {
try {
if (interactive) {
console.log('Starting Runner listener interactively');
listener = childProcess.spawn(listenerExePath, ['run'].concat(process.argv.slice(3)), { env: process.env });
} else {
console.log('Starting Runner listener with startup type: service');
listener = childProcess.spawn(listenerExePath, ['run', '--startuptype', 'service'].concat(process.argv.slice(2)), { env: process.env });
}
console.log('Started listener process');
listener.stdout.on('data', (data) => {
process.stdout.write(data.toString('utf8'));
});
listener.stderr.on('data', (data) => {
process.stdout.write(data.toString('utf8'));
});
listener.on('close', (code) => {
console.log(`Runner listener exited with error code ${code}`);
if (code === 0) {
console.log('Runner listener exit with 0 return code, stop the service, no retry needed.');
stopping = true;
} else if (code === 1) {
console.log('Runner listener exit with terminated error, stop the service, no retry needed.');
stopping = true;
} else if (code === 2) {
console.log('Runner listener exit with retryable error, re-launch runner in 5 seconds.');
} else if (code === 3) {
console.log('Runner listener exit because of updating, re-launch runner in 5 seconds.');
} else {
console.log('Runner listener exit with undefined return code, re-launch runner in 5 seconds.');
}
if(!stopping) {
setTimeout(runService, 5000);
}
});
} catch(ex) {
console.log(ex);
}
}
}
runService();
console.log('Started running service');
var gracefulShutdown = function(code) {
console.log('Shutting down runner listener');
stopping = true;
if (listener) {
console.log('Sending SIGINT to runner listener to stop');
listener.kill('SIGINT');
// TODO wait for 30 seconds and send a SIGKILL
}
}
process.on('SIGINT', () => {
gracefulShutdown(0);
});
process.on('SIGTERM', () => {
gracefulShutdown(0);
});

View File

@ -0,0 +1,20 @@
#!/bin/bash
# convert SIGTERM signal to SIGINT
# for more info on how to propagate SIGTERM to a child process see: http://veithen.github.io/2014/11/16/sigterm-propagation.html
trap 'kill -INT $PID' TERM INT
if [ -f ".path" ]; then
# configure
export PATH=`cat .path`
echo ".path=${PATH}"
fi
# insert anything to setup env when running as a service
# run the host process which keep the listener alive
./externals/node12/bin/node ./bin/RunnerService.js $* &
PID=$!
wait $PID
trap - TERM INT
wait $PID

View File

@ -0,0 +1,55 @@
#!/bin/bash
echo "Starting supervisor (Docker)"
sudo service docker start
if [ -n "${GITHUB_REPOSITORY}" ]
then
auth_url="https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPOSITORY}/actions/runners/registration-token"
registration_url="https://github.com/${GITHUB_OWNER}/${GITHUB_REPOSITORY}"
else
auth_url="https://api.github.com/orgs/${GITHUB_OWNER}/actions/runners/registration-token"
registration_url="https://github.com/${GITHUB_OWNER}"
fi
generate_token() {
payload=$(curl -sX POST -H "Authorization: token ${GITHUB_PERSONAL_TOKEN}" "${auth_url}")
runner_token=$(echo "${payload}" | jq .token --raw-output)
if [ "${runner_token}" == "null" ]
then
echo "${payload}"
exit 1
fi
echo "${runner_token}"
}
remove_runner() {
./config.sh remove --unattended --token "$(generate_token)"
}
service docker status
runner_id=${RUNNER_NAME}_$(openssl rand -hex 6)
echo "Registering runner ${runner_id}"
./config.sh \
--name "${runner_id}" \
--labels "${RUNNER_LABELS}" \
--token "$(generate_token)" \
--url "${registration_url}" \
--allowedauthorslist "${ALLOWEDAUTHORSLIST}" \
--unattended \
--replace
trap 'remove_runner; exit 130' SIGINT
trap 'remove_runner; exit 143' SIGTERM
for f in runsvc.sh RunnerService.js; do
mv bin/${f}{,.bak}
mv {patched,bin}/${f}
done
./bin/runsvc.sh --once "$*"
remove_runner