From edfbe81da7b1e2a24d1b80afe7f34395f4c01aa3 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh <rahultesnik@gmail.com> Date: Wed, 6 Apr 2022 19:58:48 +0530 Subject: [PATCH] refactor: add manager fingerprinting (#14671) Co-authored-by: Michael Kriese <michael.kriese@visualon.de> Co-authored-by: Rhys Arkins <rhys@arkins.net> --- lib/modules/manager/fingerprint.spec.ts | 13 ++++ lib/modules/manager/index.ts | 2 +- tools/generate-imports.mjs | 81 +++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 lib/modules/manager/fingerprint.spec.ts diff --git a/lib/modules/manager/fingerprint.spec.ts b/lib/modules/manager/fingerprint.spec.ts new file mode 100644 index 0000000000..bf29986163 --- /dev/null +++ b/lib/modules/manager/fingerprint.spec.ts @@ -0,0 +1,13 @@ +import { regEx } from '../../util/regex'; +import { getManagers, hashMap } from '.'; + +describe('modules/manager/fingerprint', () => { + it('validate manager hash', () => { + const regex = regEx(/^[a-f0-9]{64}$/i); + const managers = getManagers(); + for (const [manager] of managers) { + const managerHash = hashMap.get(manager); + expect(regex.test(managerHash)).toBeTrue(); + } + }); +}); diff --git a/lib/modules/manager/index.ts b/lib/modules/manager/index.ts index a7f23aac34..1cd65b45a3 100644 --- a/lib/modules/manager/index.ts +++ b/lib/modules/manager/index.ts @@ -9,7 +9,7 @@ import type { RangeConfig, Result, } from './types'; - +export { hashMap } from './fingerprint.generated'; const managerList = Array.from(managers.keys()); const languageList = Object.values(ProgrammingLanguage); diff --git a/tools/generate-imports.mjs b/tools/generate-imports.mjs index 4633a0d09e..bdce7aa37c 100644 --- a/tools/generate-imports.mjs +++ b/tools/generate-imports.mjs @@ -1,7 +1,13 @@ +import util from 'util'; import fs from 'fs-extra'; +import _glob from 'glob'; +import hasha from 'hasha'; +import minimatch from 'minimatch'; import shell from 'shelljs'; import upath from 'upath'; +const glob = util.promisify(_glob); + shell.echo('generating imports'); const newFiles = new Set(); @@ -32,6 +38,9 @@ const dataPaths = [ 'data', 'node_modules/emojibase-data/en/shortcodes/github.json', ]; +const options = { + algorithm: 'sha256', +}; /** * @@ -63,6 +72,43 @@ function expandPaths(paths) { .reduce((x, y) => x.concat(y)); } +/** + * @param {string} filePath + * @returns {Promise<string>} + */ +async function getFileHash(filePath) { + try { + const hash = await hasha.fromFile(filePath, options); + return hash; + } catch (err) { + throw new Error(`ERROR: Unable to generate hash for ${filePath}`); + } +} + +/** + * + * @param {string} managerName + * @returns {Promise<string>} + */ +export async function getManagerHash(managerName) { + /** @type {string[]} */ + let hashes = []; + const files = (await glob(`lib/modules/manager/${managerName}/**`)).filter( + (fileName) => minimatch(fileName, '*.+(snap|spec.ts)', { matchBase: true }) + ); + + for (const fileAddr of files) { + const hash = await getFileHash(fileAddr); + hashes.push(hash); + } + + if (hashes.length) { + return hasha(hashes, options); + } + + throw new Error(`Unable to generate hash for manager/${managerName}`); +} + async function generateData() { const files = expandPaths(dataPaths).sort(); @@ -93,11 +139,46 @@ async function generateData() { ); } +async function generateHash() { + shell.echo('generating hashes'); + try { + const hashMap = `export const hashMap = new Map<string, string>();`; + /** @type {string[]} */ + let hashes = []; + // get managers list + const managers = ( + await fs.readdir('lib/modules/manager', { withFileTypes: true }) + ) + .filter((file) => file.isDirectory()) + .map((file) => file.name); + + for (const manager of managers) { + const hash = await getManagerHash(manager); + hashes.push(hash); + } + + //add manager hashes to hashMap {key->manager, value->hash} + hashes = (await Promise.all(hashes)).map( + (hash, index) => `hashMap.set('${managers[index]}','${hash}');` + ); + + //write hashMap to fingerprint.generated.ts + await updateFile( + 'lib/modules/manager/fingerprint.generated.ts', + [hashMap, hashes.join('\n')].join('\n\n') + ); + } catch (err) { + shell.echo('ERROR:', err.message); + process.exit(1); + } +} + // eslint-disable-next-line @typescript-eslint/no-floating-promises (async () => { try { // data-files await generateData(); + await generateHash(); await Promise.all( shell .find('lib/**/*.generated.ts') -- GitLab