Skip to content

Commit

Permalink
fix: clear resource validator cache on modifications
Browse files Browse the repository at this point in the history
  • Loading branch information
f1ames committed Jul 12, 2023
1 parent c2ae656 commit 9342085
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 15 deletions.
42 changes: 37 additions & 5 deletions src/utils/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import logger from '../utils/logger';
import type { ExtensionContext } from 'vscode';
import type { Folder } from './workspace';

export type ConfigurableValidator = {
parser: any;
loader: any;
validator: any;
};

// Use default map with full list of plugins so it's easier
// for users to work with newly generated validation configuration file.
const DEFAULT_PLUGIN_MAP = {
Expand All @@ -24,11 +30,12 @@ const DEFAULT_PLUGIN_MAP = {
// Having multiple roots, each with different config will make it inefficient to reconfigure
// validator multiple times for a single validation run. That's why we will need separate
// validator for each root (which will be reconfigured only when root related config changes).
const VALIDATORS = new Map<string, {config: string, validator: any}>();
const VALIDATORS = new Map<string, {config: string, validator: ConfigurableValidator}>();

export async function getValidator(validatorId: string, config?: any) {
const validatorItem = VALIDATORS.get(validatorId);
const validator = validatorItem?.validator ?? await getDefaultValidator();
const validatorObj = validatorItem?.validator ?? await getConfigurableValidator();
const validator = validatorObj.validator;
const oldConfig = validatorItem?.config ?? null;
const newConfig = JSON.stringify(config);

Expand All @@ -39,7 +46,7 @@ export async function getValidator(validatorId: string, config?: any) {

VALIDATORS.set(validatorId, {
config: newConfig,
validator: validator,
validator: validatorObj,
});

return validator;
Expand All @@ -48,12 +55,14 @@ export async function getValidator(validatorId: string, config?: any) {
export async function validateFolder(root: Folder, context: ExtensionContext) {
const resources = await getWorkspaceResources(root);

logger.log(root.name, 'resources', resources);
logger.log(root.name, 'resources');

if(!resources.length) {
return null;
}

resources.forEach(resource => logger.log(resource.id, resource.name, resource.content));

const workspaceConfig = await getWorkspaceConfig(root);

logger.log(root.name, 'workspaceConfig', workspaceConfig);
Expand Down Expand Up @@ -153,14 +162,25 @@ export async function createDefaultConfigFile(destFolder: string) {
return Uri.file(filePath);
}

export async function clearResourceCache(root: Folder, resourceId: string) {
const validatorItem = VALIDATORS.get(root.id);
const parser = validatorItem?.validator?.parser;

logger.log('clearResourceCache', !!parser, root.name, resourceId);

if (parser) {
parser.clear([resourceId]);
}
}

export async function readConfig(path: string) {
const {readConfig} = await import('@monokle/validation');
return readConfig(path);
}

export async function getDefaultConfig(root: Folder) {
const validatorItem = VALIDATORS.get(root.id);
const validator = validatorItem?.validator ?? await getDefaultValidator();
const validator = validatorItem?.validator.validator ?? await getDefaultValidator();

return validator.config;
}
Expand All @@ -170,6 +190,18 @@ async function getDefaultValidator() {
return createDefaultMonokleValidator();
}

async function getConfigurableValidator() {
const {ResourceParser, SchemaLoader, MonokleValidator, createDefaultPluginLoader} = await import('@monokle/validation');
const parser = new ResourceParser();
const schemaLoader = new SchemaLoader();

return {
parser,
loader: schemaLoader,
validator: new MonokleValidator(createDefaultPluginLoader(parser, schemaLoader)),
};
}

// For some reason (according to specs? to be checked) SARIF extension doesn't like
// valid Windows paths, which are "C:\path\to\file.yaml". It expects them to have
// unix like separators, so "C:/path/to/file.yaml".
Expand Down
39 changes: 29 additions & 10 deletions src/utils/workspace.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { RelativePattern, Uri, workspace } from 'vscode';
import { readFile, readdir } from 'fs/promises';
import { basename, extname, join, normalize } from 'path';
import { basename, join, normalize } from 'path';
import { Resource, extractK8sResources } from './extract';
import { getDefaultConfig, getValidationResultPath, readConfig, validateFolder } from './validation';
import { clearResourceCache, getDefaultConfig, getValidationResultPath, readConfig, validateFolder } from './validation';
import { generateId } from './helpers';
import { SETTINGS, DEFAULT_CONFIG_FILE_NAME } from '../constants';
import logger from '../utils/logger';
Expand Down Expand Up @@ -102,19 +101,30 @@ export function initializeWorkspaceWatchers(workspaceFolders: Folder[], context:
context.isValidating = false;
};

watcher.onDidChange((uri) => {
const resetResourceCache = async (filePath: string) => {
const resourceId = await getResourceIdFromPath(folder, filePath);

if (!resourceId) {
return;
}

return clearResourceCache(folder, resourceId);
};

watcher.onDidChange(async (uri) => {
logger.log(`File ${uri.fsPath} has been changed`);
revalidateFolder();
await resetResourceCache(uri.fsPath);
await revalidateFolder();
});

watcher.onDidCreate((uri) => {
watcher.onDidCreate(async (uri) => {
logger.log(`File ${uri.fsPath} has been created`);
revalidateFolder();
await revalidateFolder();
});

watcher.onDidDelete((uri) => {
watcher.onDidDelete(async (uri) => {
logger.log(`File ${uri.fsPath} has been deleted`);
revalidateFolder();
await revalidateFolder();
});

return watcher;
Expand All @@ -138,7 +148,8 @@ async function findYamlFiles(folderPath: string): Promise<File[]> {

async function convertFilesToK8sResources(files: File[]): Promise<Resource[]> {
const filesWithContent = await Promise.all(files.map(async file => {
const content = await readFile(file.path, 'utf-8');
const contentRaw = await workspace.fs.readFile(Uri.file(file.path));
const content = Buffer.from(contentRaw.buffer).toString('utf8');

return {
id: file.id,
Expand All @@ -154,3 +165,11 @@ async function getWorkspaceLocalConfig(workspaceFolder: Folder) {
const configPath = normalize(join(workspaceFolder.uri.fsPath, DEFAULT_CONFIG_FILE_NAME));
return readConfig(configPath);
}

async function getResourceIdFromPath(folder: Folder, path: string) {
const files = await findYamlFiles(folder.uri.fsPath);
const file = files.find(file => normalize(file.path) === normalize(path));
const resources = file ? await convertFilesToK8sResources([file]) : [];

return resources.pop()?.id ?? null;
}

0 comments on commit 9342085

Please sign in to comment.