reasons: transformReasonsToArray()

in jobs/reports/repositories.ts [339:499]


            reasons: transformReasonsToArray(admin, repository.full_name),
          });
        }
      }
    }
  }
  // Send to org admins
  const orgName = repository.organization.name;
  const orgData = context.organizationData[orgName];
  for (let i = 0; orgData && orgData.organizationContext && orgData.organizationContext.recipients && orgData.organizationContext.recipients.length && i < orgData.organizationContext.recipients.length; i++) {
    repositoryContext.recipients.push(orgData.organizationContext.recipients[i]);
  }
  // Basic administrators info
  basicRepository.administrators = 'None';
  if (corporateAdministrators.length > 0) {
    let caLink = 'mailto:' + corporateAdministrators.join(';') + '?subject=' + repository.full_name;
    const peoplePlurality = corporateAdministrators.length > 1 ? 'people' : 'person';
    basicRepository.administrators = {
      link: caLink,
      text: `${corporateAdministrators.length} ${peoplePlurality}`,
    };
  }
  const actionEditCollaborators = {
    link: githubDirectLink('editRepoPermissions', null, 'settings/collaboration'),
    text: 'Permissions',
  };
  const actionDelete = {
    link: githubDirectLink('repoDeleteOrTransfer', null, 'settings'),
    text: 'Consider deleting or transferring',
  };
  const actionView = {
    link: githubDirectLink('repoBrowse'),
    text: 'Open',
  };
  const actionShip = {
    link: githubDirectLink('repoShipIt', null, 'settings'),
    text: 'Ship it',
  };
  const actionViewInPortal = context.config.urls ? {
    link: reposDirectLink('repoDetails'),
    text: 'Details',
  } : null;
  if (repositoryContext.administratorsByType.linked.length === 0 || repositoryContext.actionableAdministrators.length === 0) {
    addEntityToIssueType(context, repositoryContext, 'noRepositoryAdministrators', basicRepository, actionEditCollaborators, actionViewInPortal);
  }
  let createdAt = repository.created_at ? moment(repository.created_at) : null;
  if (createdAt) {
    basicRepository.created = createdAt.format(simpleDateFormat);
  }
  let updatedAt = repository.updated_at ? moment(repository.updated_at) : null;
  if (updatedAt) {
    basicRepository.updated = updatedAt.format(simpleDateFormat);
  }
  let pushedAt = repository.pushed_at ? moment(repository.pushed_at) : null;
  if (pushedAt) {
    basicRepository.pushed = pushedAt.format(simpleDateFormat);
  }
  let mostRecentActivityMoment = createdAt;
  let mostRecentActivity = 'Created';
  if (updatedAt && updatedAt.isAfter(mostRecentActivityMoment)) {
    mostRecentActivity = 'Updated';
    mostRecentActivityMoment = updatedAt;
  }
  if (pushedAt && pushedAt.isAfter(mostRecentActivityMoment)) {
    mostRecentActivity = 'Pushed';
    mostRecentActivityMoment = pushedAt;
  }
  const twoYearsAgo = moment().subtract(2, 'years');
  const oneYearAgo = moment().subtract(1, 'years');
  const nineMonthsAgo = moment().subtract(9, 'months');
  const thirtyDaysAgo = moment().subtract(30, 'days');
  const thisWeek = moment().subtract(7, 'days');
  const today = moment().subtract(1, 'days');
  const ageInMonths = today.diff(createdAt, 'months');
  if (ageInMonths > 0) {
    basicRepository.ageInMonths = ageInMonths === 1 ? '1 month' : ageInMonths + ' months';
  }
  const monthsSinceUpdates = today.diff(mostRecentActivityMoment, 'months');
  const timeAsString = monthsSinceUpdates + ' month' + (monthsSinceUpdates === 1 ? '' : 's');
  basicRepository.recentActivity = monthsSinceUpdates < 1 ? 'Active' : `${timeAsString} (${mostRecentActivity})`;
  if (mostRecentActivityMoment.isBefore(nineMonthsAgo)) {
    basicRepository.abandoned = {
      text: `${monthsSinceUpdates} months`,
      color: 'red',
    };
  }
  if (exemptRepositories && exemptRepositories[repository.id] && exemptRepositories[repository.id].approved && exemptRepositories[repository.id].days) {
    const exemptionExpiresAt = moment(exemptRepositories[repository.id].approved)
      .add(exemptRepositories[repository.id].days, 'days')
      .subtract(2, 'weeks');
    if (moment().isAfter(exemptionExpiresAt)) {
      basicRepository.exemptionExpiresAt = exemptionExpiresAt.format(simpleDateFormat);
      addEntityToIssueType(context, repositoryContext, 'expiringPrivateEngineeringExemptions', basicRepository, actionShip, actionDelete);
    }
  } else if (!repository.private && mostRecentActivityMoment.isBefore(twoYearsAgo)) {
    addEntityToIssueType(context, repositoryContext, 'abandonedPublicRepositories', basicRepository, actionView, actionDelete);
  } else if (repository.private && mostRecentActivityMoment.isBefore(twoYearsAgo)) {
    addEntityToIssueType(context, repositoryContext, 'twoYearOldPrivateRepositories', basicRepository, actionView, actionDelete);
  } else if (repository.private && createdAt.isBefore(oneYearAgo) && !privateEngineering) {
    addEntityToIssueType(context, repositoryContext, 'oneYearOldPrivateRepositories', basicRepository, actionView, actionDelete);
  } else if (repository.private && createdAt.isBefore(thirtyDaysAgo) && !privateEngineering) {
    addEntityToIssueType(context, repositoryContext, 'privateRepositoriesLessThanOneYear', basicRepository, actionShip, actionDelete);
  } else if (createdAt.isAfter(thisWeek) && !privateEngineering) {
    // New public and private repos
    const repositoryForManagerAndLawyer = shallowCloneWithAdditionalRecipients(basicRepository, repositoryContext.additionalRecipients);
    if (createdAt.isAfter(today)) {
      addEntityToIssueType(context, repositoryContext, 'NewReposToday', repositoryForManagerAndLawyer, actionView, actionViewInPortal);
    }
    // Always include in the weekly summary
    addEntityToIssueType(context, repositoryContext, 'NewReposWeek', repositoryForManagerAndLawyer, actionView, actionViewInPortal);
  }
  // Alert on too many administrators, excluding private engineering organizations at this time
  // NOTE: commenting out the "too many" notice for September 2017
  //if (!privateEngineering && repositoryContext.actionableAdministrators.length > context.settings.tooManyRepoAdministrators) {
  //addEntityToIssueType(context, repositoryContext, 'repositoryTooManyAdministrators', basicRepository, actionViewInPortal, actionEditCollaborators);
  //}
  if (context.settings.repoDelayAfter) {
    await sleep(context.settings.repoDelayAfter);
  }
}

function shallowCloneWithAdditionalRecipients(basicRepository: IBasicRepository, additionalRecipients) {
  const clone = Object.assign({}, basicRepository);
  if (additionalRecipients && additionalRecipients.length) {
    clone.additionalRecipients = additionalRecipients;
  }
  return clone;
}

async function getNewRepoCreationInformation(context: IReportsContext, repositoryContext: IReportsRepositoryContext, basicRepository: IBasicRepository): Promise<void> {
  const repository = repositoryContext.repository;
  const thisWeek = moment().subtract(7, 'days');
  let createdAt = repository.created_at ? moment(repository.created_at) : null;
  let isBrandNew = createdAt.isAfter(thisWeek);
  const repositoryMetadataProvider = context.providers.repositoryMetadataProvider;
  if (!isBrandNew || !repositoryMetadataProvider) {
    return;
  }
  const releaseTypeMapping = context.config && context.config.github && context.config.github.approvalTypes && context.config.github.approvalTypes.fields ? context.config.github.approvalTypes.fields.approvalIdsToReleaseType : null;
  let approval = null;
  try {
    approval = await repositoryMetadataProvider.getRepositoryMetadata(repository.id);
  } catch (approvalGetError) {
    return;
  }
  if (!approval) {
    return;
  }
  if (approval.repositoryId == repositoryContext.repository.id /* not strict equal, data client IDs are strings vs GitHub responses use numbers */ ||
    approval.organizationName && approval.organizationName.toLowerCase() === repositoryContext.repository.organization.name.toLowerCase()) {
    basicRepository.approvalLicense = approval.initialLicense;
    basicRepository.approvalJustification = approval.releaseReviewJustification;
    if (approval.releaseReviewType && releaseTypeMapping) {
      const approvalTypes = Object.getOwnPropertyNames(releaseTypeMapping);
      for (let j = 0; j < approvalTypes.length; j++) {
        const id = approvalTypes[j];
        const title = releaseTypeMapping[id];
        if (approval.projectType === id) {
          basicRepository.approvalTypeId = approval.projectType; // ?
          // Hard-coded specific to show justification text or approval links
          if ((id === 'NewReleaseReview' || id === 'ExistingReleaseReview') && approval.releaseReviewUrl) {