-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from collabsoft-net/next
Preparing 1.2.0 release
- Loading branch information
Showing
62 changed files
with
16,475 additions
and
965 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,6 @@ | |
.yarn/install-state.gz | ||
dist/ | ||
lib/ | ||
node_modules | ||
coverage/ | ||
node_modules | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/* eslint-disable */ | ||
|
||
/* | ||
THIS IS A VERBATIM COPY OF THE EXIT HOOK IMPLEMENTATION | ||
The only change in this mock is that the `isCalled` and `isRegistered` variables are reset | ||
For some reason, vi.resetModules() does not clear exit-hook and these values do not get reset between tests | ||
If the `isCalled` variable is not reset, exit-hook will not process gracefullExit again | ||
Because we depend on gracefullExit to capture error messages and convey them to Commander.JS, this breaks tests | ||
*/ | ||
|
||
import process from 'node:process'; | ||
|
||
const asyncCallbacks = new Set(); | ||
const callbacks = new Set(); | ||
|
||
let isCalled = false; | ||
let isRegistered = false; | ||
|
||
async function exit(shouldManuallyExit, isSynchronous, signal) { | ||
if (isCalled) { | ||
return; | ||
} | ||
|
||
isCalled = true; | ||
|
||
if (asyncCallbacks.size > 0 && isSynchronous) { | ||
console.error([ | ||
'SYNCHRONOUS TERMINATION NOTICE:', | ||
'When explicitly exiting the process via process.exit or via a parent process,', | ||
'asynchronous tasks in your exitHooks will not run. Either remove these tasks,', | ||
'use gracefulExit() instead of process.exit(), or ensure your parent process', | ||
'sends a SIGINT to the process running this code.', | ||
].join(' ')); | ||
} | ||
|
||
const exitCode = 128 + signal; | ||
|
||
const done = (force = false) => { | ||
if (force === true || shouldManuallyExit === true) { | ||
isCalled = false; | ||
isRegistered = false; | ||
process.exit(exitCode); // eslint-disable-line unicorn/no-process-exit | ||
} | ||
}; | ||
|
||
for (const callback of callbacks) { | ||
callback(exitCode); | ||
} | ||
|
||
if (isSynchronous) { | ||
done(); | ||
return; | ||
} | ||
|
||
const promises = []; | ||
let forceAfter = 0; | ||
for (const [callback, wait] of asyncCallbacks) { | ||
forceAfter = Math.max(forceAfter, wait); | ||
promises.push(Promise.resolve(callback(exitCode))); | ||
} | ||
|
||
// Force exit if we exceeded our wait value | ||
const asyncTimer = setTimeout(() => { | ||
done(true); | ||
}, forceAfter); | ||
|
||
await Promise.all(promises); | ||
clearTimeout(asyncTimer); | ||
done(); | ||
} | ||
|
||
function addHook(options) { | ||
const {onExit, wait, isSynchronous} = options; | ||
const asyncCallbackConfig = [onExit, wait]; | ||
|
||
if (isSynchronous) { | ||
callbacks.add(onExit); | ||
} else { | ||
asyncCallbacks.add(asyncCallbackConfig); | ||
} | ||
|
||
if (!isRegistered) { | ||
isRegistered = true; | ||
|
||
// Exit cases that support asynchronous handling | ||
process.once('beforeExit', exit.bind(undefined, true, false, -128)); | ||
process.once('SIGINT', exit.bind(undefined, true, false, 2)); | ||
process.once('SIGTERM', exit.bind(undefined, true, false, 15)); | ||
|
||
// Explicit exit events. Calling will force an immediate exit and run all | ||
// synchronous hooks. Explicit exits must not extend the node process | ||
// artificially. Will log errors if asynchronous calls exist. | ||
process.once('exit', exit.bind(undefined, false, true, 0)); | ||
|
||
// PM2 Cluster shutdown message. Caught to support async handlers with pm2, | ||
// needed because explicitly calling process.exit() doesn't trigger the | ||
// beforeExit event, and the exit event cannot support async handlers, | ||
// since the event loop is never called after it. | ||
process.on('message', message => { | ||
if (message === 'shutdown') { | ||
exit(true, true, -128); | ||
} | ||
}); | ||
} | ||
|
||
return () => { | ||
if (isSynchronous) { | ||
callbacks.delete(onExit); | ||
} else { | ||
asyncCallbacks.delete(asyncCallbackConfig); | ||
} | ||
}; | ||
} | ||
|
||
export default function exitHook(onExit) { | ||
if (typeof onExit !== 'function') { | ||
throw new TypeError('onExit must be a function'); | ||
} | ||
|
||
return addHook({ | ||
onExit, | ||
isSynchronous: true, | ||
}); | ||
} | ||
|
||
export function asyncExitHook(onExit, options = {}) { | ||
if (typeof onExit !== 'function') { | ||
throw new TypeError('onExit must be a function'); | ||
} | ||
|
||
if (!(typeof options.wait === 'number' && options.wait > 0)) { | ||
throw new TypeError('wait must be set to a positive numeric value'); | ||
} | ||
|
||
return addHook({ | ||
onExit, | ||
wait: options.wait, | ||
isSynchronous: false, | ||
}); | ||
} | ||
|
||
export function gracefulExit(signal = 0) { | ||
exit(true, false, -128 + signal); | ||
} |
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
|
||
import axios from 'axios'; | ||
import console from 'console'; | ||
import { writeFileSync } from 'fs'; | ||
import { setTimeout } from 'timers'; | ||
|
||
const repositories = [ | ||
{ name: 'jira', repository: 'atlassian/jira-software' }, | ||
{ name: 'confluence', repository: 'atlassian/confluence' }, | ||
{ name: 'bamboo', repository: 'atlassian/bamboo-server' }, | ||
{ name: 'bitbucket', repository: 'atlassian/bitbucket-server' }, | ||
{ name: 'mysql', repository: 'library/mysql' }, | ||
{ name: 'postgresql', repository: 'library/postgres' }, | ||
]; | ||
|
||
const getListOfTagsPaginated = async (url) => { | ||
const tags = []; | ||
const { data } = await axios.get(url); | ||
if (data) { | ||
tags.push(...data.results.map(item => item.name)); | ||
|
||
if (data.next) { | ||
// Add a backoff period to avoid rate limiting | ||
await new Promise(resolve => setTimeout(resolve, 100)); | ||
tags.push(...await getListOfTagsPaginated(data.next)); | ||
} | ||
} | ||
|
||
return tags; | ||
} | ||
|
||
(async () => { | ||
const result = await repositories.reduce(async (previous, item) => { | ||
const result = await previous; | ||
console.log(`Retrieving list of tags for ${item.name}...`); | ||
const tags = await getListOfTagsPaginated(`https://hub.docker.com/v2/repositories/${item.repository}/tags/?page_size=100`); | ||
result[item.name] = tags; | ||
return result; | ||
}, Promise.resolve({})); | ||
|
||
// Microsft SQL Server has it's own registry with a different API | ||
console.log(`Retrieving list of tags for mssql...`); | ||
const { data } = await axios.get('https://mcr.microsoft.com/v2/mssql/server/tags/list'); | ||
result['mssql'] = data.tags; | ||
|
||
const output = {}; | ||
Object.entries(result).forEach(([ key, value ]) => output[key] = value); | ||
writeFileSync('assets/versions.json', JSON.stringify(output)); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.