mirror of https://github.com/cncf/landscapeapp.git
190 lines
5.9 KiB
JavaScript
190 lines
5.9 KiB
JavaScript
const colors = require('colors');
|
|
const Promise = require('bluebird');
|
|
const _ = require('lodash');
|
|
const path = require('path');
|
|
const debug = require('debug')('bestpractices');
|
|
|
|
const { errorsReporter } = require('./reporter');
|
|
const { requestWithRetry } = require('./requestWithRetry');
|
|
const { projectPath } = require('./settings');
|
|
const { makeReporter } = require('./progressReporter');
|
|
const { retry } = require('./retry');
|
|
|
|
const { addError } = errorsReporter('bestpractices');
|
|
|
|
const errorColor = colors.red;
|
|
const cacheMiss = colors.green;
|
|
|
|
|
|
async function getLandscapeItems() {
|
|
const source = require('js-yaml').load(require('fs').readFileSync(path.resolve(projectPath, 'landscape.yml')));
|
|
const traverse = require('traverse');
|
|
const tree = traverse(source);
|
|
const items = [];
|
|
tree.map(function(node) {
|
|
if (!node) {
|
|
return;
|
|
}
|
|
if (node.item !== null) {
|
|
return;
|
|
}
|
|
if (node.repo_url === null) {
|
|
return;
|
|
}
|
|
items.push({repo_url: node.url_for_bestpractices || node.repo_url});
|
|
});
|
|
return items;
|
|
}
|
|
|
|
async function fetchEntriesNoRetry() {
|
|
const maxNumber = 300;
|
|
const items = await Promise.map(_.range(1, maxNumber), async function(number) {
|
|
const result = await requestWithRetry({
|
|
url: `https://bestpractices.coreinfrastructure.org/en/projects.json?page=${number}`
|
|
});
|
|
return result.map(x => ({
|
|
id: x.id,
|
|
repo_url: x.repo_url,
|
|
percentage: x.badge_percentage_0
|
|
})).filter(x => !!x.repo_url);
|
|
}, {concurrency: 1});
|
|
return _.flatten(items);
|
|
}
|
|
|
|
async function fetchEntryNoRetry(url) {
|
|
let result = await requestWithRetry({
|
|
json: true,
|
|
url: `https://bestpractices.coreinfrastructure.org/en/projects.json?pq=${encodeURIComponent(url)}`
|
|
});
|
|
if (result[0]) {
|
|
result = result[0];
|
|
}
|
|
return {
|
|
id: result.id,
|
|
repo_url: result.repo_url,
|
|
percentage: result.badge_percentage_0
|
|
};
|
|
}
|
|
|
|
async function fetchEntries() {
|
|
return await retry(fetchEntriesNoRetry, 3);
|
|
}
|
|
|
|
async function fetchEntry(url) {
|
|
return await retry(() => fetchEntryNoRetry(url), 3);
|
|
}
|
|
|
|
module.exports.fetchBestPracticeEntriesWithFullScan = async function({cache, preferCache}) {
|
|
const items = await getLandscapeItems();
|
|
const errors = [];
|
|
var fetchedEntries = null;
|
|
const reporter = makeReporter();
|
|
const result = await Promise.mapSeries(items, async function(item) {
|
|
if (!item.repo_url) {
|
|
return null;
|
|
}
|
|
const cachedEntry = _.find(cache, (c) => c.repo_url.toLowerCase() === item.repo_url.toLowerCase());
|
|
if (cachedEntry && preferCache) {
|
|
debug(`Full scan: Cache found for ${item.repo_url}`);
|
|
reporter.write('.');
|
|
return cachedEntry;
|
|
}
|
|
debug(`Full scan: Cache not found for ${item.repo_url}`);
|
|
try {
|
|
fetchedEntries = fetchedEntries || await fetchEntries();
|
|
let repo_url = item.repo_url;
|
|
let badge = _.find(fetchedEntries, (x) => x.repo_url.toLowerCase() === item.repo_url.toLowerCase());
|
|
if (!badge && item.project_org) {
|
|
repo_url = item.project_org;
|
|
badge = _.find(fetchedEntries, (x) => x.repo_url.toLowerCase() === item.project_org.toLowerCase());
|
|
}
|
|
reporter.write(cacheMiss("*"));
|
|
return ({
|
|
repo_url: repo_url,
|
|
badge: badge ? badge.id : false,
|
|
percentage: badge ? badge.percentage : null
|
|
});
|
|
} catch (ex) {
|
|
debug(`Full scan: Fetch failed for ${item.repo_url}, attempt to use a cached entry`);
|
|
reporter.write(errorColor("E"));
|
|
errors.push(`Cannot fetch: ${item.repo_url} `, ex.message.substring(0, 200));
|
|
return cachedEntry || null;
|
|
}
|
|
});
|
|
reporter.summary();
|
|
_.each(errors, function(e) {
|
|
addError(e);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
module.exports.fetchBestPracticeEntriesWithIndividualUrls = async function({cache, preferCache}) {
|
|
const items = await getLandscapeItems();
|
|
const errors = [];
|
|
const reporter = makeReporter();
|
|
const result = await Promise.mapSeries(items, async function(item) {
|
|
if (!item.repo_url) {
|
|
return null;
|
|
}
|
|
let cachedEntry = _.find(cache, (c) => c.repo_url.toLowerCase() === item.repo_url.toLowerCase());
|
|
if (!cachedEntry && item.project_org) {
|
|
cachedEntry = _.find(cache, (c) => c.repo_url.toLowerCase() === item.project_org.toLowerCase());
|
|
}
|
|
if (cachedEntry && preferCache) {
|
|
reporter.write('.');
|
|
return cachedEntry;
|
|
}
|
|
debug(`Individual scan: Cache not found for ${item.repo_url}`);
|
|
try {
|
|
let repo_url = item.repo_url;
|
|
let badge = await fetchEntry(item.repo_url);
|
|
if (!badge && item.project_org) {
|
|
repo_url = item.project_org;
|
|
badge = await fetchEntry(item.project_org);
|
|
}
|
|
reporter.write(cacheMiss("*"));
|
|
return ({
|
|
repo_url: repo_url,
|
|
badge: badge ? badge.id : false,
|
|
percentage: badge ? badge.percentage : null
|
|
});
|
|
} catch (ex) {
|
|
debug(`Individual scan: Fetch failed for ${item.repo_url}, attempt to use a cached entry`);
|
|
reporter.write(errorColor("E"));
|
|
errors.push(`Cannot fetch: ${item.repo_url} `, ex.message.substring(0, 200));
|
|
return cachedEntry || null;
|
|
}
|
|
});
|
|
reporter.summary();
|
|
_.each(errors, function(error) {
|
|
console.info('error: ', error);
|
|
});
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
module.exports.extractSavedBestPracticeEntries = async function extractSavedBestPracticeEntries() {
|
|
const traverse = require('traverse');
|
|
let source = [];
|
|
try {
|
|
source = require('js-yaml').load(require('fs').readFileSync(path.resolve(projectPath, 'processed_landscape.yml')));
|
|
} catch(_ex) {
|
|
console.info('Cannot extract image entries from the processed_landscape.yml');
|
|
}
|
|
|
|
var entries = [];
|
|
const tree = traverse(source);
|
|
tree.map(function(node) {
|
|
if (!node) {
|
|
return;
|
|
}
|
|
if (node.best_practice_data && node.repo_url) {
|
|
entries.push({...node.best_practice_data, repo_url: node.url_for_bestpractices || node.repo_url});
|
|
}
|
|
});
|
|
|
|
return _.uniq(entries);
|
|
}
|