From b79ea980b8cde78ca4f622e971c6908fcfeea61d Mon Sep 17 00:00:00 2001 From: Yury Tsarev Date: Mon, 5 Oct 2020 01:58:20 +0200 Subject: [PATCH] Use self update ready entrypoint (#99) * Use self update ready entrypoint * Add --once support for runsvc.sh Run `cd runner; NAME=$DOCKER_USER/actions-runner TAG=dev make docker-build docker-push`, `kubectl apply -f release/actions-runner-controller.yaml`, then update the runner image(not the controller image) by updating e.g. `Runner.Spec.Image` to `$DOCKER_USER/actions-runner:$TAG`, for testing. Co-authored-by: Yusuke Kuoka --- runner/Dockerfile | 1 + runner/Makefile | 5 +- runner/entrypoint.sh | 8 ++- runner/patched/RunnerService.js | 91 +++++++++++++++++++++++++++++++++ runner/patched/runsvc.sh | 20 ++++++++ 5 files changed, 122 insertions(+), 3 deletions(-) create mode 100755 runner/patched/RunnerService.js create mode 100755 runner/patched/runsvc.sh diff --git a/runner/Dockerfile b/runner/Dockerfile index c7b612b9..632545f3 100644 --- a/runner/Dockerfile +++ b/runner/Dockerfile @@ -55,6 +55,7 @@ RUN mkdir -p /runner \ && rm -rf /var/lib/apt/lists/* COPY entrypoint.sh /runner +COPY patched /runner/patched USER runner:runner ENTRYPOINT ["/usr/local/bin/dumb-init", "--"] diff --git a/runner/Makefile b/runner/Makefile index 0f319f24..fb598155 100644 --- a/runner/Makefile +++ b/runner/Makefile @@ -1,11 +1,12 @@ NAME ?= summerwind/actions-runner +TAG ?= latest RUNNER_VERSION ?= 2.273.4 DOCKER_VERSION ?= 19.03.12 docker-build: - docker build --build-arg RUNNER_VERSION=${RUNNER_VERSION} --build-arg DOCKER_VERSION=${DOCKER_VERSION} -t ${NAME}:latest -t ${NAME}:v${RUNNER_VERSION} . + docker build --build-arg RUNNER_VERSION=${RUNNER_VERSION} --build-arg DOCKER_VERSION=${DOCKER_VERSION} -t ${NAME}:${TAG} -t ${NAME}:v${RUNNER_VERSION} . docker-push: - docker push ${NAME}:latest + docker push ${NAME}:${TAG} docker push ${NAME}:v${RUNNER_VERSION} diff --git a/runner/entrypoint.sh b/runner/entrypoint.sh index 56cb7281..3989998e 100755 --- a/runner/entrypoint.sh +++ b/runner/entrypoint.sh @@ -28,5 +28,11 @@ fi cd /runner ./config.sh --unattended --replace --name "${RUNNER_NAME}" --url "https://github.com/${ATTACH}" --token "${RUNNER_TOKEN}" ${LABEL_ARG} +for f in runsvc.sh RunnerService.js; do + diff {bin,patched}/${f} || : + sudo mv bin/${f}{,.bak} + sudo mv {patched,bin}/${f} +done + unset RUNNER_NAME RUNNER_REPO RUNNER_TOKEN -exec ./run.sh --once +exec ./bin/runsvc.sh --once diff --git a/runner/patched/RunnerService.js b/runner/patched/RunnerService.js new file mode 100755 index 00000000..4062ac3c --- /dev/null +++ b/runner/patched/RunnerService.js @@ -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); +}); \ No newline at end of file diff --git a/runner/patched/runsvc.sh b/runner/patched/runsvc.sh new file mode 100755 index 00000000..39cebc05 --- /dev/null +++ b/runner/patched/runsvc.sh @@ -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 \ No newline at end of file