creevey
Version:
Cross-browser screenshot testing tool for Storybook with fancy UI Runner
145 lines (117 loc) • 5.06 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.pullImages = pullImages;
exports.runImage = runImage;
exports.default = _default;
var _cluster = _interopRequireWildcard(require("cluster"));
var _types = require("../types");
var _messages = require("./messages");
var _utils = require("./utils");
var _dockerode = _interopRequireDefault(require("dockerode"));
var _stream = require("stream");
var _ora = _interopRequireDefault(require("ora"));
var _logger = require("./logger");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const docker = new _dockerode.default();
class DevNull extends _stream.Writable {
_write(_chunk, _encoding, callback) {
setImmediate(callback);
}
}
async function pullImages(images, auth) {
_logger.logger.info('Pull docker images');
for (const image of images) {
await new Promise((resolve, reject) => {
const spinner = (0, _ora.default)(`${image}: Pull start`).start(); // eslint-disable-next-line @typescript-eslint/no-floating-promises
docker.pull(image, {
authconfig: auth
}, function (pullError, stream) {
if (pullError) {
spinner.fail();
return reject(pullError);
} // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
docker.modem.followProgress(stream, onFinished, onProgress);
function onFinished(error) {
if (error) {
spinner.fail();
return reject(error);
}
spinner.succeed(`${image}: Pull complete`);
resolve();
}
function onProgress(event) {
if (!/^[a-z0-9]{12}$/i.test(event.id)) return;
spinner.text = `${image}: [${event.id}] ${event.status} ${event.progress ? `${event.progress}` : ''}`;
}
});
});
}
}
async function runImage(image, args, options, debug) {
await Promise.all((await docker.listContainers({
all: true,
filters: {
ancestor: [image]
}
})).map(async info => {
const container = docker.getContainer(info.Id);
try {
await container.stop();
} catch (_) {
/* noop */
}
await container.remove();
}));
const hub = docker.run(image, args, debug ? process.stdout : new DevNull(), options, error => {
if (error) throw error;
});
return new Promise(resolve => {
hub.once('container', container => {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
(0, _messages.subscribeOn)('shutdown', async () => {
try {
await container.stop();
await container.remove();
} catch (error) {
/* noop */
}
});
});
hub.once('start', container => void container.inspect().then(info => resolve(info.NetworkSettings.Networks.bridge.IPAddress)));
});
}
async function _default(config, browser, startContainer) {
if (_cluster.isMaster) {
const host = await startContainer();
let gridUrl = 'http://localhost:4444/wd/hub';
gridUrl = _utils.isInsideDocker ? gridUrl.replace(_utils.LOCALHOST_REGEXP, host) : gridUrl;
_cluster.default.on('message', (worker, message) => {
if (!(0, _types.isDockerMessage)(message)) return;
const dockerMessage = message;
if (dockerMessage.type != 'start') return;
(0, _messages.sendDockerMessage)(worker, {
type: 'success',
payload: {
gridUrl
}
});
});
} else {
if (browser && config.browsers[browser].gridUrl) return Promise.resolve();
return new Promise(resolve => {
(0, _messages.subscribeOn)('docker', message => {
if (message.type == 'success') {
config.gridUrl = message.payload.gridUrl;
resolve();
}
});
(0, _messages.emitDockerMessage)({
type: 'start'
});
});
}
}