@ 261105.4
current
import qs from 'node:querystring';
import { getPrURL } from '../links.js';

import {
  CI_DOMAIN,
  parseJobFromURL,
  CI_TYPES
} from './ci_type_parser.js';

export const statusType = {
  SUCCESS: 'SUCCESS',
  FAILURE: 'FAILURE',
  ABORTED: 'ABORTED',
  UNSTABLE: 'UNSTABLE'
};

export function getCIActionAdvice(pr, action) {
  const command = `ncu-ci ${action} ${getPrURL(pr)}`;
  if (action === 'run') {
    return 'Check the existing CI run in Jenkins and rebase the PR if needed. ' +
      `To start a new CI run manually: ${command}`;
  }
  if (pr.owner === 'nodejs' && pr.repo === 'node') {
    return `Resume CI by adding the "resume-ci" label to the PR, or run: ${command}`;
  }
  return `Resume CI with: ${command}`;
}

export function getPath(url) {
  return url.replace(`https://${CI_DOMAIN}/`, '').replace('api/json', '');
}

export function getNodeName(url) {
  const re = /\/nodes=(.+?)\//;
  if (re.test(url)) {
    return url.match(re)[1];
  }
  const parts = url.split('/');
  return parts[parts.length - 3];
}

export function fold(summary, code) {
  const dataBlock = '```\n' + code + '\n```';
  const summaryBlock = `\n<summary>${summary}</summary>\n`;
  return `<details>${summaryBlock}\n${dataBlock}\n</details>`;
}

export function pad(any, length) {
  return (any + '').padEnd(length);
}

export function markdownRow(...args) {
  let result = '';
  for (const item of args) {
    result += `| ${item} `;
  }
  return result + '|\n';
}

function filterBuild(builds, type) {
  return builds
    .filter(build => build.result === type)
    .map(build => parseJobFromURL(build.url));
}

export async function listBuilds(cli, request, type, since) {
  // assert(type === COMMIT || type === PR)
  const { jobName } = CI_TYPES.get(type);
  const tree = 'builds[url,result,timestamp,actions[parameters[name,value]]]';
  const url = `https://${CI_DOMAIN}/job/${jobName}/api/json?tree=${qs.escape(tree)}`;

  cli.startSpinner(`Querying ${url}`);

  const result = await request.json(url);
  let builds = result.builds.filter(build => !build.actions?.some(action =>
    action.parameters?.some(({ name, value }) =>
      (name === 'TARGET_GITHUB_ORG' || name === 'GITHUB_ORG') &&
      typeof value === 'string' && value.toLowerCase() === 'nodejs-private')));
  if (since) {
    builds = builds.filter(build => build.timestamp > since);
  }
  const failed = filterBuild(builds, statusType.FAILURE);
  const aborted = filterBuild(builds, statusType.ABORTED);
  const pending = filterBuild(builds, null);
  const unstable = filterBuild(builds, statusType.UNSTABLE);
  const success = filterBuild(builds, statusType.SUCCESS);
  cli.stopSpinner('Done');

  return {
    success,
    failed,
    aborted,
    pending,
    unstable,
    count: builds.length
  };
}

export function getHighlight(f) {
  if (!f.reason) {
    f.reason = 'failure not found';
    return f.reason;
  }
  return f.reason.split('\n')[f.highlight]
    .replace(/not ok \d+ /, '')
    .replace(
      /JNLP4-connect connection from \S+/, 'JNLP4-connect connection from ...'
    )
    .replace(/FATAL: Could not checkout \w+/, 'FATAL: Could not checkout ...')
    .replace(
      /error: pathspec .+ did not match any file\(s\) known to git/,
      'error: pathspec ... did not match any file(s) known to git')
    .replace(
      /failed: no workspace for .+/,
      'failed: no workspace for ...'
    )
    .replace(
      /fatal: loose object \w+ \(stored in .git\/objects\/.+\) is corrupt/,
      'fatal: loose object ... (stored in .git/objects/...) is corrupt')
    .replace(/hudson\.plugins\.git\.GitException: /, '')
    .replace(/java\.io\.IOException: /, '');
}