deflake 1.2.8 → 1.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +55 -23
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -715,7 +715,6 @@ async function runDoctor(argv) {
|
|
|
715
715
|
}
|
|
716
716
|
|
|
717
717
|
async function applySelfHealing(result) {
|
|
718
|
-
|
|
719
718
|
if (!result.location || !result.location.fullRootPath || !result.fix) return;
|
|
720
719
|
|
|
721
720
|
try {
|
|
@@ -727,28 +726,55 @@ async function applySelfHealing(result) {
|
|
|
727
726
|
return;
|
|
728
727
|
}
|
|
729
728
|
|
|
730
|
-
let
|
|
729
|
+
let patches = [];
|
|
731
730
|
try {
|
|
732
731
|
const parsed = JSON.parse(result.fix);
|
|
733
|
-
if (parsed.
|
|
734
|
-
|
|
732
|
+
if (parsed.patches && Array.isArray(parsed.patches)) {
|
|
733
|
+
patches = parsed.patches;
|
|
734
|
+
} else if (parsed.code) {
|
|
735
|
+
patches = [{
|
|
736
|
+
file: filePath,
|
|
737
|
+
line: targetLine,
|
|
738
|
+
action: 'REPLACE',
|
|
739
|
+
new_line: parsed.code
|
|
740
|
+
}];
|
|
741
|
+
}
|
|
742
|
+
} catch (e) {
|
|
743
|
+
// Fallback for raw string fixes
|
|
744
|
+
patches = [{
|
|
745
|
+
file: filePath,
|
|
746
|
+
line: targetLine,
|
|
747
|
+
action: 'REPLACE',
|
|
748
|
+
new_line: result.fix
|
|
749
|
+
}];
|
|
750
|
+
}
|
|
735
751
|
|
|
736
|
-
const
|
|
737
|
-
|
|
752
|
+
for (const patch of patches) {
|
|
753
|
+
const pFile = patch.file || filePath;
|
|
754
|
+
const pLine = parseInt(patch.line || targetLine);
|
|
755
|
+
const pAction = patch.action || 'REPLACE';
|
|
756
|
+
let pNew = patch.new_line;
|
|
738
757
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
758
|
+
if (!fs.existsSync(pFile)) continue;
|
|
759
|
+
|
|
760
|
+
const lines = fs.readFileSync(pFile, 'utf8').split('\n');
|
|
761
|
+
const originalLineIndex = pLine - 1;
|
|
743
762
|
|
|
744
|
-
|
|
745
|
-
// For robustness, we replace the whole line but keep indentation
|
|
746
|
-
const originalLine = lines[originalLineIndex];
|
|
747
|
-
const indentation = originalLine.match(/^\s*/)[0];
|
|
748
|
-
lines[originalLineIndex] = indentation + fixCode.trim();
|
|
763
|
+
if (originalLineIndex < 0 || originalLineIndex >= lines.length) continue;
|
|
749
764
|
|
|
750
|
-
|
|
751
|
-
|
|
765
|
+
const originalLine = lines[originalLineIndex];
|
|
766
|
+
const indentation = originalLine.match(/^\s*/)[0];
|
|
767
|
+
|
|
768
|
+
if (pAction === 'INSERT_AFTER') {
|
|
769
|
+
lines.splice(pLine, 0, indentation + pNew.trim());
|
|
770
|
+
fs.writeFileSync(pFile, lines.join('\n'));
|
|
771
|
+
console.log(` ✅ ${C.GREEN}[Self-Healing] Successfully inserted at:${C.RESET} ${path.basename(pFile)}:${pLine}`);
|
|
772
|
+
} else {
|
|
773
|
+
lines[originalLineIndex] = indentation + pNew.trim();
|
|
774
|
+
fs.writeFileSync(pFile, lines.join('\n'));
|
|
775
|
+
console.log(` ✅ ${C.GREEN}[Self-Healing] Successfully patched:${C.RESET} ${path.basename(pFile)}:${pLine}`);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
752
778
|
} catch (error) {
|
|
753
779
|
console.error(` ❌ ${C.RED}[Self-Healing] Error patching file:${C.RESET} ${error.message}`);
|
|
754
780
|
}
|
|
@@ -956,10 +982,6 @@ async function analyzeFailures(artifacts, fullLog, client) {
|
|
|
956
982
|
console.log(`\n${C.BRIGHT}💡 Tip: Use ${C.CYAN}--fix${C.RESET}${C.BRIGHT} to automatically apply these suggested fixes next time.${C.RESET}`);
|
|
957
983
|
}
|
|
958
984
|
|
|
959
|
-
// TRIGGER REPORT
|
|
960
|
-
if (results.length > 0 && argv.fix && argv.report) {
|
|
961
|
-
showFrameworkReport();
|
|
962
|
-
}
|
|
963
985
|
|
|
964
986
|
return results.length;
|
|
965
987
|
}
|
|
@@ -985,6 +1007,7 @@ async function runCommand(cmd, args) {
|
|
|
985
1007
|
|
|
986
1008
|
async function main() {
|
|
987
1009
|
const command = argv._ || [];
|
|
1010
|
+
let finalExitCode = 0;
|
|
988
1011
|
|
|
989
1012
|
// If 'doctor' or 'migrate' was called, don't proceed to wrapper logic
|
|
990
1013
|
if (command.includes('doctor') || command.includes('migrate')) return;
|
|
@@ -1005,26 +1028,35 @@ async function main() {
|
|
|
1005
1028
|
const artifacts = detectAllArtifacts(null, argv.html);
|
|
1006
1029
|
const fixesApplied = await analyzeFailures(artifacts, output, client);
|
|
1007
1030
|
|
|
1031
|
+
let outcomeCode = code;
|
|
1008
1032
|
// AUTO-VERIFICATION
|
|
1009
1033
|
if (fixesApplied > 0 && argv.fix) {
|
|
1010
1034
|
console.log(`\n${C.BRIGHT}💉 Fixes applied. Re-running tests to verify...${C.RESET}`);
|
|
1011
1035
|
const secondRun = await runCommand(cmd, args);
|
|
1036
|
+
outcomeCode = secondRun.code;
|
|
1012
1037
|
if (secondRun.code === 0) {
|
|
1013
1038
|
console.log(`\n${C.GREEN}${C.BRIGHT}✅ All tests passed after DeFlake healing!${C.RESET}`);
|
|
1014
1039
|
} else {
|
|
1015
1040
|
console.log(`\n${C.YELLOW}⚠️ Some tests still failing after fixes. Check the report for details.${C.RESET}`);
|
|
1016
1041
|
}
|
|
1017
1042
|
}
|
|
1018
|
-
|
|
1043
|
+
finalExitCode = outcomeCode;
|
|
1019
1044
|
} else {
|
|
1020
1045
|
console.log("\n🟢 Command passed successfully.");
|
|
1021
|
-
|
|
1046
|
+
finalExitCode = 0;
|
|
1022
1047
|
}
|
|
1023
1048
|
} else {
|
|
1024
1049
|
const artifacts = detectAllArtifacts(argv.log, argv.html);
|
|
1025
1050
|
const fullLog = argv.log && fs.existsSync(argv.log) ? fs.readFileSync(argv.log, 'utf8') : null;
|
|
1026
1051
|
await analyzeFailures(artifacts, fullLog, client);
|
|
1027
1052
|
}
|
|
1053
|
+
|
|
1054
|
+
// FINAL REPORT TRIGGER
|
|
1055
|
+
if (argv.report) {
|
|
1056
|
+
showFrameworkReport();
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
process.exit(finalExitCode);
|
|
1028
1060
|
}
|
|
1029
1061
|
|
|
1030
1062
|
// main() call is now handled by the check above
|