UNPKG

@nrwl/insights

Version:

Nx Insights plugin for Nx

232 lines 8.36 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const rxjs_1 = require("rxjs"); const tasks_runner_v2_1 = require("@nrwl/workspace/src/tasks-runner/tasks-runner-v2"); const fs = require("fs"); const fs_1 = require("fs"); const path = require("path"); const uuid_1 = require("uuid"); const operators_1 = require("rxjs/operators"); const axios = require('axios'); const tar = require('tar'); class InsightsApi { constructor(baseUrl, authToken) { this.uniqRunId = uuid_1.v4(); const [_, access] = new Buffer(authToken, 'base64').toString().split('|'); this.isReadWrite = access === 'read-write'; this.axiosInstance = axios.create({ baseURL: baseUrl, timeout: 30000, headers: { authorization: authToken } }); } startTask(task) { return this.axiosInstance.post('/nx-insights/tasks/start', { taskId: `${task.id}-${this.uniqRunId}`, startTime: new Date().toISOString(), target: task.target.target, projectName: task.target.project, hash: task.hash }); } endTask(task) { return this.axiosInstance.post('/nx-insights/tasks/end', { taskId: `${task.id}-${this.uniqRunId}`, endTime: new Date().toISOString() }); } storeCache(hash) { return __awaiter(this, void 0, void 0, function* () { const resp = yield this.axiosInstance({ method: 'get', url: `/nx-insights/cache/store/${hash}` }); if (!resp.data || !resp.data.url || !(typeof resp.data.url === 'string')) { throw new Error(`Invalid remote cache response: ${JSON.stringify(resp.data)}`); } return resp.data.url; }); } retrieveCache(hash) { return __awaiter(this, void 0, void 0, function* () { const resp = yield this.axiosInstance({ method: 'get', url: `/nx-insights/cache/${hash}` }); if (!resp.data || !resp.data.url || !(typeof resp.data.url === 'string')) { throw new Error(`Invalid remote cache response: ${JSON.stringify(resp.data)}`); } return resp.data.url; }); } } class InsightsRemoteCache { constructor(api) { this.api = api; } retrieve(hash, cacheDirectory) { return __awaiter(this, void 0, void 0, function* () { try { const url = yield this.api.retrieveCache(hash); const tgz = this.createFileName(hash, cacheDirectory); yield this.downloadFile(url, tgz); this.createCommitFile(hash, cacheDirectory); return true; } catch (e) { if (e.response && e.response.status === 404) { // cache miss. print nothing } else { this.printErrorMessage(e); } return false; } }); } store(hash, cacheDirectory) { return __awaiter(this, void 0, void 0, function* () { if (this.api.isReadWrite) { try { const url = yield this.api.storeCache(hash); const tgz = yield this.createFile(hash, cacheDirectory); yield this.uploadFile(url, tgz); return true; } catch (e) { this.printErrorMessage(e); return false; } } else { return true; } }); } printErrorMessage(e) { if (e.code === 'ECONNREFUSED' || e.code === 'EAI_AGAIN' || e.code === 'ENOTFOUND') { console.error(`Error: Cannot connect to remote cache.`); } else if (e.response.status === 401) { console.error(`Error: Invalid Nx Insights access token.`); } else { console.error(e.message); } } createFileName(hash, cacheDirectory) { return path.join(cacheDirectory, `${hash}.tar.gz`); } downloadFile(url, tgz) { return __awaiter(this, void 0, void 0, function* () { const resp = yield axios(url, { method: 'GET', responseType: 'stream', maxContentLength: 1000 * 1000 * 200 }); const q = resp.data.pipe(tar.x({ cwd: path.dirname(tgz) })); return new Promise(res => { q.on('close', () => { res(); }); }); }); } createCommitFile(hash, cacheDirectory) { fs_1.writeFileSync(path.join(cacheDirectory, `${hash}.commit`), 'true'); } createFile(hash, cacheDirectory) { return __awaiter(this, void 0, void 0, function* () { const tgz = this.createFileName(hash, cacheDirectory); yield tar.c({ gzip: true, file: tgz, cwd: cacheDirectory }, [hash]); return tgz; }); } uploadFile(url, tgz) { return __awaiter(this, void 0, void 0, function* () { yield axios(url, { method: 'PUT', data: fs.readFileSync(tgz), headers: { 'Content-Type': 'application/octet-stream' }, maxContentLength: 1000 * 1000 * 200 }); }); } } const insightsTaskRunner = (tasks, options, context) => { if (process.env.NX_INSIGHTS_AUTH_TOKEN || options.accessToken) { const api = createApi(options); const lifeCycle = new TaskRunnerLifeCycle(api); const remoteCache = new InsightsRemoteCache(api); const res = tasks_runner_v2_1.tasksRunnerV2(tasks, Object.assign({}, options, { remoteCache, lifeCycle }), context); return lifeCycle.complete().pipe(operators_1.concatMap(() => res)); } else { return tasks_runner_v2_1.tasksRunnerV2(tasks, options, context); } }; class TaskRunnerLifeCycle { constructor(api) { this.api = api; this.promises = {}; this.errors = []; } startTask(task) { if (this.api.isReadWrite) { this.promises[`${task.id}-start`] = this.api.startTask(task).catch(e => { this.errors.push(e.message); }); } } endTask(task, code) { if (this.api.isReadWrite) { const endPromise = this.promises[`${task.id}-start`] .then(() => { return this.api.endTask(task); }) .catch((e) => { this.errors.push(e.message); }); this.promises[`${task.id}-end`] = endPromise; } } complete() { return rxjs_1.from(Promise.all(Object.values(this.promises)).then(() => { if (this.errors.length > 0) { this.printNxInsightsStatus(); } })); } printNxInsightsStatus() { console.warn(`We were unable to send the data to Nx Insights:`); console.error(`Errors:`); console.error(this.errors[0]); } } function createApi(options) { const baseUrl = options.insightsUrl || 'https://nrwl.api.io'; if (process.env.NX_INSIGHTS_AUTH_TOKEN) { return new InsightsApi(baseUrl, process.env.NX_INSIGHTS_AUTH_TOKEN); } else { return new InsightsApi(baseUrl, options.accessToken); } } exports.default = insightsTaskRunner; //# sourceMappingURL=insights-task-runner.js.map