import * as Sentry from '@sentry/browser'; import { pickBy } from 'lodash'; import { createNodeDict } from './components/parsing_utils'; import { SUPPORTED_FILTER_PARAMETERS } from './constants'; export const validateParams = (params) => { return pickBy(params, (val, key) => SUPPORTED_FILTER_PARAMETERS.includes(key) && val); }; /** * This function takes the stages array and transform it * into a hash where each key is a job name and the job data * is associated to that key. * @param {Array} stages * @returns {Object} - Hash of jobs */ export const createJobsHash = (stages = []) => { const nodes = stages.flatMap(({ groups }) => groups); return createNodeDict(nodes); }; /** * This function takes the jobs hash generated by * `createJobsHash` function and returns an easier * structure to work with for needs relationship * where the key is the job name and the value is an * array of all the needs this job has recursively * (includes the needs of the needs) * @param {Object} jobs * @returns {Object} - Hash of jobs and array of needs */ export const generateJobNeedsDict = (jobs = {}) => { const arrOfJobNames = Object.keys(jobs); return arrOfJobNames.reduce((acc, value) => { const recursiveNeeds = (jobName) => { if (!jobs[jobName]?.needs) { return []; } return jobs[jobName].needs .reduce((needsAcc, job) => { // It's possible that a needs refer to an optional job // that is not defined in which case we don't add that entry if (!jobs[job]) { return needsAcc; } // If we already have the needs of a job in the accumulator, // then we use the memoized data instead of the recursive call // to save some performance. const newNeeds = acc[job] ?? recursiveNeeds(job); // In case it's a parallel job (size > 1), the name of the group // and the job will be different. This mean we also need to add the group name // to the list of `needs` to ensure we can properly reference it. const group = jobs[job]; if (group.size > 1) { return [...needsAcc, job, group.name, newNeeds]; } return [...needsAcc, job, newNeeds]; }, []) .flat(Infinity); }; // To ensure we don't have duplicates job relationship when 2 jobs // needed by another both depends on the same jobs, we remove any // duplicates from the array. const uniqueValues = Array.from(new Set(recursiveNeeds(value))); return { ...acc, [value]: uniqueValues }; }, {}); }; export const reportToSentry = (component, failureType) => { Sentry.withScope((scope) => { scope.setTag('component', component); Sentry.captureException(failureType); }); }; export const reportMessageToSentry = (component, message, context) => { Sentry.withScope((scope) => { // eslint-disable-next-line @gitlab/require-i18n-strings scope.setContext('Vue data', context); scope.setTag('component', component); Sentry.captureMessage(message); }); };