Created Keep Running (kr) command
This commit is contained in:
commit
510d299276
|
@ -0,0 +1,18 @@
|
|||
name: Bonsai CI
|
||||
run-name: ${{ gitea.actor }} is running spotify.local CI pipeline 🚀
|
||||
on: [release]
|
||||
concurrency: 'true'
|
||||
|
||||
jobs:
|
||||
Build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Download dependencies
|
||||
run: npm ci
|
||||
- name: Build binairy files
|
||||
run: npm run build
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: bin
|
|
@ -0,0 +1,3 @@
|
|||
.idea/
|
||||
node_modules/
|
||||
out/
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
SLEEP=${1:-'10'}
|
||||
|
||||
echo "Sleeping for $SLEEP seconds...";
|
||||
|
||||
sleep $SLEEP;
|
||||
|
||||
echo "Waking up!";
|
||||
|
||||
exit 1;
|
|
@ -0,0 +1,213 @@
|
|||
{
|
||||
"name": "kr",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "kr",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
"kr": "src/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.8.10",
|
||||
"@types/yargs": "^17.0.29"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz",
|
||||
"integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
"version": "17.0.31",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.31.tgz",
|
||||
"integrity": "sha512-bocYSx4DI8TmdlvxqGpVNXOgCNR1Jj0gNPhhAY+iz1rgKDAaYrAYdFYnhDV1IFuiuVc9HkOwyDcFxaTElF3/wg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/yargs-parser": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/yargs-parser": {
|
||||
"version": "21.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
|
||||
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
|
||||
"dependencies": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "kr",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"bin": "src/index.js",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"build": "pkg package.json"
|
||||
},
|
||||
"pkg": {
|
||||
"scripts": "src/**/*.js",
|
||||
"targets": [
|
||||
"node18-linux-x64",
|
||||
"node18-macos-x64",
|
||||
"node18-win-x64"
|
||||
],
|
||||
"outputPath": "out"
|
||||
},
|
||||
"author": "Ian Wijma",
|
||||
"dependencies": {
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.8.10",
|
||||
"@types/yargs": "^17.0.29"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
const Yargs = require('yargs');
|
||||
const {spawn} = require("child_process");
|
||||
|
||||
const SECONDS_IN_A_MINUTE = 60;
|
||||
const SECONDS_IN_A_HOUR = 60 * 60;
|
||||
|
||||
const yargs = Yargs(process.argv.splice(2))
|
||||
.scriptName('kr')
|
||||
.usage('kr [args] <thing-to-run>')
|
||||
.option('rpm', {
|
||||
default: 0,
|
||||
description: 'The amount of Retries Per Minute, before we stop retrying',
|
||||
type: 'number'
|
||||
})
|
||||
.option('rph', {
|
||||
default: 0,
|
||||
description: 'The amount of Retries Per Hour, before we stop retrying',
|
||||
type: 'number'
|
||||
})
|
||||
.help();
|
||||
|
||||
const { _ = [], rpm, rph } = yargs.argv;
|
||||
const [command, ...args ] = _;
|
||||
|
||||
if (!command) {
|
||||
return yargs.showHelp();
|
||||
}
|
||||
|
||||
let historyMax = 4;
|
||||
let seconds = SECONDS_IN_A_MINUTE;
|
||||
let restartName = 'minute';
|
||||
|
||||
if (rpm && rph) {
|
||||
return console.error('Currently, can not define both --rpm and --rph, please choose only one.');
|
||||
} else if (rpm) {
|
||||
historyMax = rpm
|
||||
} else if (rph) {
|
||||
historyMax = rph
|
||||
seconds = SECONDS_IN_A_HOUR
|
||||
restartName = 'hour'
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Object<number, string>}
|
||||
*/
|
||||
const history = {};
|
||||
|
||||
/**
|
||||
* @param {string} logs
|
||||
*/
|
||||
const pushHistory = (logs) => history[(new Date).getTime()] = logs;
|
||||
|
||||
const updateHistory = () => {
|
||||
const clearKeys = [];
|
||||
|
||||
const maxAge = (new Date).getTime() + seconds;
|
||||
for (const historyTime in history) {
|
||||
if (historyTime > maxAge) {
|
||||
clearKeys.push(historyTime)
|
||||
}
|
||||
}
|
||||
|
||||
clearKeys.forEach((key) => delete history[key]);
|
||||
}
|
||||
|
||||
const checkHistory = () => Object.keys(history).length <= historyMax;
|
||||
|
||||
const runCommand = () => {
|
||||
console.log(`Running ${command} ${args.join(' ')}`);
|
||||
const runner = spawn(command, args);
|
||||
|
||||
const commandLogs = [];
|
||||
|
||||
const pushLog = (logEntry) => commandLogs.push(logEntry);
|
||||
|
||||
const trimLog = () => {
|
||||
if(commandLogs.length > 5000) commandLogs.shift()
|
||||
};
|
||||
|
||||
const clearLogs = () => commandLogs.length = 0;
|
||||
|
||||
const getLogs = () => commandLogs.join('\n');
|
||||
|
||||
const handleOut = (type, message) => {
|
||||
pushLog(`[${type}]\t${message}`);
|
||||
trimLog();
|
||||
};
|
||||
|
||||
const handleExit = (exitCode) => {
|
||||
console.log(`[CRASH] exit code: ${exitCode}`)
|
||||
if (exitCode !== 0) {
|
||||
pushHistory(getLogs());
|
||||
clearLogs();
|
||||
updateHistory();
|
||||
if (checkHistory()) {
|
||||
console.log('Restarting...');
|
||||
runCommand();
|
||||
} else {
|
||||
console.error(`The process crashed more then ${historyMax} times in the past ${restartName}, stop retrying.`);
|
||||
console.error(`See below the past ${historyMax} crashes:`);
|
||||
for (const time in history) {
|
||||
console.error(`Crash @ ${time}:\n${history[time]}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runner.on('close', (exitCode) => handleExit(exitCode))
|
||||
runner.stdout.on('data', (data) => console.log(data.toString().trim()))
|
||||
runner.stdout.on('data', (data) => handleOut('stdout', data.toString().trim()))
|
||||
runner.stderr.on('data', (data) => handleOut('stderr', data.toString().trim()))
|
||||
}
|
||||
|
||||
// Command goes BRRRR
|
||||
runCommand();
|
Loading…
Reference in New Issue