Skip to content

Commit

Permalink
feat(@snyk/fix): show which parent manifest fixes occurred in
Browse files Browse the repository at this point in the history
When an item was already fixed, mention though which targetFile
  • Loading branch information
lili2311 committed Apr 12, 2021
1 parent 8f399b5 commit 3a68874
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
RemediationChanges,
Workspace,
} from '../../../../types';
import { PluginFixResponse } from '../../../types';
import { FixedCache, PluginFixResponse } from '../../../types';
import { updateDependencies } from './update-dependencies';
import { MissingRemediationDataError } from '../../../../lib/errors/missing-remediation-data';
import { MissingFileNameError } from '../../../../lib/errors/missing-file-name';
Expand Down Expand Up @@ -41,16 +41,19 @@ export async function pipRequirementsTxt(
handlerResult.skipped.push(...notFixable);

const ordered = sortByDirectory(fixable);
const fixedFilesCache: string[] = [];
let fixedFilesCache: FixedCache = {};
for (const dir of Object.keys(ordered)) {
debug(`Fixing entities in directory ${dir}`);
const entitiesPerDirectory = ordered[dir].map((e) => e.entity);
const { failed, succeeded, skipped, fixedFiles } = await fixAll(
const { failed, succeeded, skipped, fixedCache } = await fixAll(
entitiesPerDirectory,
options,
fixedFilesCache,
);
fixedFilesCache.push(...fixedFiles);
fixedFilesCache = {
...fixedFilesCache,
...fixedCache,
};
handlerResult.succeeded.push(...succeeded);
handlerResult.failed.push(...failed);
handlerResult.skipped.push(...skipped);
Expand Down Expand Up @@ -83,8 +86,8 @@ export function getRequiredData(
async function fixAll(
entities: EntityToFix[],
options: FixOptions,
fixedCache: string[],
): Promise<PluginFixResponse & { fixedFiles: string[] }> {
fixedCache: FixedCache,
): Promise<PluginFixResponse & { fixedCache: FixedCache }> {
const handlerResult: PluginFixResponse = {
succeeded: [],
failed: [],
Expand All @@ -95,27 +98,42 @@ async function fixAll(
try {
const { dir, base } = pathLib.parse(targetFile);
// parse & join again to support correct separator
if (fixedCache.includes(pathLib.normalize(pathLib.join(dir, base)))) {
const filePath = pathLib.normalize(pathLib.join(dir, base));
if (
Object.keys(fixedCache).includes(
pathLib.normalize(pathLib.join(dir, base)),
)
) {
handlerResult.succeeded.push({
original: entity,
changes: [{ success: true, userMessage: 'Previously fixed' }],
changes: [
{
success: true,
userMessage: `Fixed through ${fixedCache[filePath].fixedIn}`,
},
],
});
continue;
}
const { changes, fixedFiles } = await applyAllFixes(entity, options);
const { changes, fixedMeta } = await applyAllFixes(entity, options);
if (!changes.length) {
debug('Manifest has not changed!');
throw new NoFixesCouldBeAppliedError();
}
fixedCache.push(...fixedFiles);
Object.keys(fixedMeta).forEach((f) => {
fixedCache[f] = {
fixedIn: targetFile,
};
});
handlerResult.succeeded.push({ original: entity, changes });
} catch (e) {
debug(`Failed to fix ${targetFile}.\nERROR: ${e}`);
handlerResult.failed.push({ original: entity, error: e });
}
}
return { ...handlerResult, fixedFiles: [] };
return { ...handlerResult, fixedCache };
}

// TODO: optionally verify the deps install
export async function fixIndividualRequirementsTxt(
workspace: Workspace,
Expand Down Expand Up @@ -154,11 +172,16 @@ export async function fixIndividualRequirementsTxt(
export async function applyAllFixes(
entity: EntityToFix,
options: FixOptions,
): Promise<{ changes: FixChangesSummary[]; fixedFiles: string[] }> {
): Promise<{
changes: FixChangesSummary[];
fixedMeta: { [filePath: string]: FixChangesSummary[] };
}> {
const { remediation, targetFile: entryFileName, workspace } = getRequiredData(
entity,
);
const fixedFiles: string[] = [];
const fixedMeta: {
[filePath: string]: FixChangesSummary[];
} = {};
const { dir, base } = pathLib.parse(entryFileName);
const provenance = await extractProvenance(workspace, dir, base);
const upgradeChanges: FixChangesSummary[] = [];
Expand All @@ -178,7 +201,7 @@ export async function applyAllFixes(
);
appliedUpgradeRemediation.push(...appliedRemediation);
upgradeChanges.push(...changes);
fixedFiles.push(pathLib.normalize(pathLib.join(dir, fileName)));
fixedMeta[pathLib.normalize(pathLib.join(dir, fileName))] = upgradeChanges;
}

/* Apply all left over remediation as pins in the entry targetFile */
Expand All @@ -199,7 +222,7 @@ export async function applyAllFixes(
directUpgradesOnly,
);

return { changes: [...upgradeChanges, ...pinnedChanges], fixedFiles };
return { changes: [...upgradeChanges, ...pinnedChanges], fixedMeta };
}

function filterOutAppliedUpgrades(
Expand Down
7 changes: 7 additions & 0 deletions packages/snyk-fix/src/plugins/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
EntityToFix,
FixChangesSummary,
FixOptions,
WithError,
WithFixChangesApplied,
Expand All @@ -19,3 +20,9 @@ export interface PluginFixResponse {
export interface FixHandlerResultByPlugin {
[pluginId: string]: PluginFixResponse;
}

export interface FixedCache {
[filePath: string]: {
fixedIn: string;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Successful fixes:
✔ Pinned transitive from 1.0.1 to 2.0.1 (pinned in app-with-constraints/constraints.txt)
app-with-constraints/lib/requirements.txt
Previously fixed
Fixed through app-with-constraints/requirements.txt
Summary:
Expand All @@ -29,10 +29,10 @@ Successful fixes:
✔ Upgraded Jinja2 from 2.7.2 to 2.7.3 (upgraded in app-with-already-fixed/lib/requirements.txt)
app-with-already-fixed/core/requirements.txt
Previously fixed
Fixed through app-with-already-fixed/requirements.txt
app-with-already-fixed/lib/requirements.txt
Previously fixed
Fixed through app-with-already-fixed/requirements.txt
Summary:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1118,7 +1118,7 @@ describe('fix *req*.txt / *.txt Python projects', () => {
expect(result.results.python.succeeded[1].changes).toEqual([
{
success: true,
userMessage: 'Previously fixed',
userMessage: 'Fixed through app-with-constraints/requirements.txt',
},
]);
});
Expand Down

0 comments on commit 3a68874

Please sign in to comment.