From f293501b0f2a996f26b59b847cc85a0e5e6b8ddf Mon Sep 17 00:00:00 2001 From: Josh Feingold Date: Wed, 3 Jul 2024 14:11:46 -0500 Subject: [PATCH 01/14] FIX (DevOps) @W-16151756@ Clean up interim-branch. (#1537) --- .github/workflows/create-release-branch.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/create-release-branch.yml b/.github/workflows/create-release-branch.yml index b58e859a6..f6d95b29a 100644 --- a/.github/workflows/create-release-branch.yml +++ b/.github/workflows/create-release-branch.yml @@ -144,7 +144,9 @@ jobs: NEW_VERSION=$(jq -r ".version" package.json) git checkout -b release-$NEW_VERSION git push --set-upstream origin release-$NEW_VERSION - # Output the branch name so we can use it in later jobs. + # Now that we're done with the interim branch, delete it. + git push -d ${NEW_VERSION}-interim + # Output the release branch name so we can use it in later jobs. echo "branch_name=release-$NEW_VERSION" >> "$GITHUB_OUTPUT" # Run all the various tests against the newly created branch. test-release-branch: From 08d1acc11ff8f4483f4b1d935adee301993f6add Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Wed, 3 Jul 2024 14:34:04 -0400 Subject: [PATCH 02/14] FIX (CodeAnalyzer): @W-16162277@: Do not require target files to exist when calculating projectDir --- messages/run-common.md | 4 ---- src/lib/InputProcessor.ts | 15 +++++++-------- test/lib/InputProcessor.test.ts | 26 ++++---------------------- 3 files changed, 11 insertions(+), 34 deletions(-) diff --git a/messages/run-common.md b/messages/run-common.md index 0327a061d..8e421f217 100644 --- a/messages/run-common.md +++ b/messages/run-common.md @@ -74,10 +74,6 @@ The selected output format doesn't match the output file type. Output format: %s --projectdir must specify existing paths -# validations.noFilesFoundInTarget - -No files were found in the target. --target must contain at least one file. - # info.resolvedTarget The --target flag wasn't specified so the default target '.' will be used. diff --git a/src/lib/InputProcessor.ts b/src/lib/InputProcessor.ts index d5a5497f2..2643e3d4b 100644 --- a/src/lib/InputProcessor.ts +++ b/src/lib/InputProcessor.ts @@ -2,9 +2,7 @@ import {Inputs} from "../types"; import {RunOptions} from "./RuleManager"; import {RunOutputOptions} from "./output/RunResultsProcessor"; import {inferFormatFromOutfile, OutputFormat} from "./output/OutputFormat"; -import {SfError} from "@salesforce/core"; import {BundleName, getMessage} from "../MessageCatalog"; -import {INTERNAL_ERROR_CODE} from "../Constants"; import {Display} from "./Display"; import normalize = require('normalize-path'); import path = require('path'); @@ -53,9 +51,14 @@ export class InputProcessorImpl implements InputProcessor { // If projectdir is not provided then: // * We calculate the first common parent directory that includes all the target files. + // --> If there are no target files, then we return the current working directory // --> If none of its parent folders contain a sfdx-project.json file, then we return this first common parent. // --> Otherwise we return the folder that contains the sfdx-project.json file. - const commonParentFolder = getFirstCommonParentFolder(this.getAllTargetFiles(inputs)); + const allTargetFiles: string[] = this.getAllTargetFiles(inputs); + if (allTargetFiles.length == 0) { + return [process.cwd()]; + } + const commonParentFolder = getFirstCommonParentFolder(allTargetFiles); let projectFolder: string = findFolderThatContainsSfdxProjectFile(commonParentFolder); projectFolder = projectFolder.length > 0 ? projectFolder : commonParentFolder if (displayResolvedProjectDir) { @@ -100,11 +103,7 @@ export class InputProcessorImpl implements InputProcessor { private getAllTargetFiles(inputs: Inputs): string[] { const targetPaths: string[] = this.resolveTargetPaths(inputs).map(p => trimMethodSpecifier(p)) - const allAbsoluteTargetFiles: string[] = globby.sync(targetPaths).map(p => path.resolve(p)); - if (allAbsoluteTargetFiles.length == 0) { - throw new SfError(getMessage(BundleName.CommonRun, 'validations.noFilesFoundInTarget'), null, null, INTERNAL_ERROR_CODE); - } - return allAbsoluteTargetFiles; + return globby.sync(targetPaths).map(p => path.resolve(p)); } private displayInfoOnlyOnce(messageKey: string, tokens?: Tokens) { diff --git a/test/lib/InputProcessor.test.ts b/test/lib/InputProcessor.test.ts index a1e9715e4..2a203464f 100644 --- a/test/lib/InputProcessor.test.ts +++ b/test/lib/InputProcessor.test.ts @@ -129,34 +129,16 @@ describe("InputProcessorImpl Tests", async () => { const inputs: Inputs = { target: ['thisFileDoesNotExist.xml', 'thisFileAlsoDoesNotExist.json'] }; - let errorThrown: boolean; - let message: string; - try { - inputProcessor.resolveProjectDirPaths(inputs); - errorThrown = false; - } catch (e) { - errorThrown = true; - message = e.message; - } - expect(errorThrown).to.equal(true, 'Error should have been thrown'); - expect(message).to.equal(getMessage(BundleName.CommonRun, 'validations.noFilesFoundInTarget')); + const projectDirPaths: string[] = inputProcessor.resolveProjectDirPaths(inputs); + expect(projectDirPaths).to.deep.equal([process.cwd()]); }) it("Unspecified projectdir with glob target that resolves to no files", async () => { const inputs: Inputs = { target: ['**.filesOfThisTypeShouldNotExist'] }; - let errorThrown: boolean; - let message: string; - try { - inputProcessor.resolveProjectDirPaths(inputs); - errorThrown = false; - } catch (e) { - errorThrown = true; - message = e.message; - } - expect(errorThrown).to.equal(true, 'Error should have been thrown'); - expect(message).to.equal(getMessage(BundleName.CommonRun, 'validations.noFilesFoundInTarget')); + const projectDirPaths: string[] = inputProcessor.resolveProjectDirPaths(inputs); + expect(projectDirPaths).to.deep.equal([process.cwd()]); }) }) }) From 2b84c1e34a59af76470bf98a7c3bd02272ecae54 Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Tue, 9 Jul 2024 09:35:06 -0400 Subject: [PATCH 03/14] Add in tests --- test/commands/scanner/run.test.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/commands/scanner/run.test.ts b/test/commands/scanner/run.test.ts index 422a493b2..477c24425 100644 --- a/test/commands/scanner/run.test.ts +++ b/test/commands/scanner/run.test.ts @@ -523,6 +523,26 @@ describe('scanner run', function () { getMessage(BundleName.CommonRun, 'internal.outfileMustBeSupportedType', [ENV_VAR_NAMES.SCANNER_INTERNAL_OUTFILE])); }); }); + + describe('When zero files targeted are with --target', () => { + it('When --target is a folder that contains zero relevant files to scan', () => { + const emptyFolder = fs.mkdtempSync(path.join(os.tmpdir(), 'empty-folder')); + const output = runCommand(`scanner run --target ${emptyFolder}`); + fs.rmSync(emptyFolder, {recursive: true, force: true}); + + assertNoError(output); + expect(output.shellOutput.stdout).to.contain('No rule violations found'); + }); + + it('When --target is a glob that finds zero files', () => { + const jsOnlyFolder = path.join('test', 'code-fixtures', 'projects', 'js', 'src'); + const globThatGivesZeroFiles = jsOnlyFolder + path.sep + '*.cls'; // There are no cls files in the js folder + const output = runCommand(`scanner run --target ${globThatGivesZeroFiles}`); + + assertNoError(output); + expect(output.shellOutput.stdout).to.contain('No rule violations found'); + }); + }); }); function validateXmlOutput(xml: string): void { From 8a8e9a6bf0142e4ecc59daf703438865ed548aac Mon Sep 17 00:00:00 2001 From: Josh Feingold Date: Wed, 17 Jul 2024 09:53:08 -0500 Subject: [PATCH 04/14] CHANGE (CodeAnalyzer): @W-16206934@: Upgraded dependencies. (#1545) --- cli-messaging/build.gradle.kts | 2 +- sfge/build.gradle.kts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cli-messaging/build.gradle.kts b/cli-messaging/build.gradle.kts index 8bca89439..f55a7011a 100644 --- a/cli-messaging/build.gradle.kts +++ b/cli-messaging/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { exclude("junit") } implementation("com.google.code.gson:gson:2.10.1") - implementation("com.google.guava:guava:31.1-jre") + implementation("com.google.guava:guava:33.2.1-jre") testImplementation("org.hamcrest:hamcrest:2.2") testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.2") diff --git a/sfge/build.gradle.kts b/sfge/build.gradle.kts index 8801a503e..c143a3e9c 100644 --- a/sfge/build.gradle.kts +++ b/sfge/build.gradle.kts @@ -15,13 +15,13 @@ dependencies { implementation(project(":cli-messaging")) implementation("commons-cli:commons-cli:1.4") implementation("org.apache.commons:commons-collections4:4.4") - implementation("org.apache.tinkerpop:tinkergraph-gremlin:3.5.1") - implementation("org.apache.tinkerpop:gremlin-driver:3.5.1") + implementation("org.apache.tinkerpop:tinkergraph-gremlin:3.5.8") + implementation("org.apache.tinkerpop:gremlin-driver:3.5.8") implementation("org.antlr:antlr-runtime:3.5.2") implementation("org.apache.logging.log4j:log4j-api:2.17.1") implementation("org.apache.logging.log4j:log4j-core:2.17.1") implementation("com.google.code.gson:gson:2.10.1") - implementation("com.google.guava:guava:26.0-jre") + implementation("com.google.guava:guava:33.2.1-jre") implementation("com.google.code.findbugs:jsr305:3.0.2") implementation ("com.googlecode.json-simple:json-simple:1.1.1") { exclude("junit") From 9d9c90dd84ae6bdcd6770a355c80d7a72f0e523e Mon Sep 17 00:00:00 2001 From: Josh Feingold Date: Wed, 17 Jul 2024 12:05:58 -0500 Subject: [PATCH 05/14] CHANGE (RetireJS): @W-16253670@: RetireJS now provides better feedback for bad ZIPs. (#1547) --- messages/RetireJsEngine.md | 11 ++++++ src/MessageCatalog.ts | 1 + src/lib/retire-js/RetireJsEngine.ts | 32 +++++++++++++++--- test/lib/retire-js/RetireJsEngine.test.ts | 20 +++++++++++ .../invalid-zips/ZipInInvalidFormat.zip | Bin 0 -> 335 bytes 5 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 messages/RetireJsEngine.md create mode 100644 test/test-zips/invalid-zips/ZipInInvalidFormat.zip diff --git a/messages/RetireJsEngine.md b/messages/RetireJsEngine.md new file mode 100644 index 000000000..e1c20a747 --- /dev/null +++ b/messages/RetireJsEngine.md @@ -0,0 +1,11 @@ +# error.couldNotGetZipEntries + +Failed to get entries from ZIP file %s. Reason: %s. + +# error.couldNotReadEntryData + +Failed to read contents of entry %s in ZIP file %s. Reason: %s. + +# error.couldNotExtractZip + +Failed to extract ZIP file %s. Reason: %s. diff --git a/src/MessageCatalog.ts b/src/MessageCatalog.ts index 8e4f084f4..75efdad8b 100644 --- a/src/MessageCatalog.ts +++ b/src/MessageCatalog.ts @@ -24,6 +24,7 @@ export enum BundleName { PmdEngine = "PmdEngine", PmdLanguageManager = "PmdLanguageManager", Remove = "remove", + RetireJsEngine = 'RetireJsEngine', Run = "run-pathless", RunDfa = "run-dfa", RunOutputProcessor = "RunOutputProcessor", diff --git a/src/lib/retire-js/RetireJsEngine.ts b/src/lib/retire-js/RetireJsEngine.ts index b4df1e1de..ee01f8003 100644 --- a/src/lib/retire-js/RetireJsEngine.ts +++ b/src/lib/retire-js/RetireJsEngine.ts @@ -11,6 +11,7 @@ import cspawn = require('cross-spawn'); import path = require('path'); import StreamZip = require('node-stream-zip'); import {CUSTOM_CONFIG} from '../../Constants'; +import {BundleName, getMessage} from '../../MessageCatalog'; import * as fs from "node:fs"; // Note that we don't want to call npx retire from this file since we don't want to accidentally have npx pick up @@ -513,18 +514,34 @@ export class RetireJsEngine extends AbstractRuleEngine { storeEntries: true }); - // Not sure why, but this method demands an argument that doesn't seem to be used anywhere. Passing in null. - const entries = await zip.entries(null); + let entries: {[p: string]: StreamZip.ZipEntry}; + try { + // Not sure why, but this method demands an argument that doesn't seem to be used anywhere. Passing in null. + entries = await zip.entries(null); + } catch (e) { + const reason = e instanceof Error ? e.message : e as string; + throw new Error(getMessage(BundleName.RetireJsEngine, 'error.couldNotGetZipEntries', [zipSrc, reason])); + } // Iterate over every entry in the ZIP. for (const {name, isDirectory} of Object.values(entries)) { // Skip directories and non-text files. - if (isDirectory || this.srh.identifyBufferType(await zip.entryData(name)) !== StaticResourceType.TEXT) { + if (isDirectory) { + continue; + } + let buffer: Buffer; + try { + buffer = await zip.entryData(name); + } catch (e) { + const reason = e instanceof Error ? e.message : e as string; + throw new Error(getMessage(BundleName.RetireJsEngine, 'error.couldNotReadEntryData', [name, zipSrc, reason])); + } + if (this.srh.identifyBufferType(buffer) !== StaticResourceType.TEXT) { continue; } // Each zipped text file needs to be mapped to an alias corresponding to its location within the ZIP. // That way, each violation can be tied to an individual file within the ZIP instead of the ZIP as a whole. - const originalPath =`${zipSrc}:${name}`; + const originalPath = `${zipSrc}:${name}`; // We derive the alias path using the path to the ZIP's alias folder, and any pathing information within the // file itself. If there's no corresponding directory yet, we need to create it. @@ -537,7 +554,12 @@ export class RetireJsEngine extends AbstractRuleEngine { // Combine the two to get our full alias path. const aliasPath = path.join(aliasDir, aliasFile); this.originalFilesByAlias.set(aliasPath, originalPath); - await zip.extract(name, aliasPath); + try { + await zip.extract(name, aliasPath); + } catch (e) { + const reason = e instanceof Error ? e.message : e as string; + throw new Error(getMessage(BundleName.RetireJsEngine, 'error.couldNotExtractZip', [zipSrc, reason])); + } } return await zip.close(); } diff --git a/test/lib/retire-js/RetireJsEngine.test.ts b/test/lib/retire-js/RetireJsEngine.test.ts index 3ead35aa8..0676a0769 100644 --- a/test/lib/retire-js/RetireJsEngine.test.ts +++ b/test/lib/retire-js/RetireJsEngine.test.ts @@ -226,6 +226,26 @@ describe('RetireJsEngine', () => { expect(actualDupedFiles.has(fullPath)).to.equal(true, `Zip contents ${fullPath} should be aliased`); } } + }); + + it('Unparseable ZIP causes clear error', async () => { + // Create a target that simulates a glob matching a ZIP we know won't parse. + const invalidTarget : RuleTarget = { + target: path.join('test', 'test-zips', 'invalid-zips', 'ZipInInvalidFormat.zip'), + targetType: TargetType.GLOB, + paths: [path.join('test', 'test-zips', 'invalid-zips', 'ZipInInvalidFormat.zip')] + }; + + let errorThrown: boolean = false; + let errorMessage: string; + try { + await (testEngine as any).createTmpDirWithDuplicatedTargets([invalidTarget]); + } catch (e) { + errorThrown = true; + errorMessage = e.message; + } + expect(errorThrown).to.equal(true); + expect(errorMessage).to.contain('Failed to get entries from ZIP'); }); diff --git a/test/test-zips/invalid-zips/ZipInInvalidFormat.zip b/test/test-zips/invalid-zips/ZipInInvalidFormat.zip new file mode 100644 index 0000000000000000000000000000000000000000..f562db21181ede89ccfd657e9b302259a46524e8 GIT binary patch literal 335 zcmd1F$=55XDDgCsi*!GtJ%8&B8p9m4TI^fe9$h@c$lz4u}ScFfeiS@J~!% z%@xGRU>)Gi$RxrHv3(BE_Qy}BZr}kb1Yu5)4lqz?Skee$fL#r8KC(7!j)rIxXn5;r m3}nK+fUpajCm@0}fb@D0hXDZLi$Ib9 literal 0 HcmV?d00001 From 7a3a4cc1ea7329d793e568f9e9f0b4397f6db90b Mon Sep 17 00:00:00 2001 From: Josh Feingold Date: Wed, 24 Jul 2024 15:24:54 -0500 Subject: [PATCH 06/14] FIX (PMD): @W-15708421@: Read PMD results from outfile instead of stdout. (#1551) --- src/lib/pmd/PmdCommandInfo.ts | 6 +++--- src/lib/pmd/PmdEngine.ts | 21 +++++++++++++-------- src/lib/pmd/PmdWrapper.ts | 5 ++++- test/lib/pmd/PmdEngine.test.ts | 12 ++++++------ 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/lib/pmd/PmdCommandInfo.ts b/src/lib/pmd/PmdCommandInfo.ts index 7133877b4..f7d16f77a 100644 --- a/src/lib/pmd/PmdCommandInfo.ts +++ b/src/lib/pmd/PmdCommandInfo.ts @@ -8,7 +8,7 @@ export interface PmdCommandInfo { getJarPathForLanguage(lang: string): string - constructJavaCommandArgsForPmd(fileList: string, classPathsForExternalRules: string[], rulesets: string): string[] + constructJavaCommandArgsForPmd(fileList: string, classPathsForExternalRules: string[], rulesets: string, outfile: string): string[] constructJavaCommandArgsForCpd(fileList: string, minimumTokens: number, language: string): string[] } @@ -22,10 +22,10 @@ export class Pmd7CommandInfo implements PmdCommandInfo { return path.join(PMD7_LIB, `pmd-${language}-${this.getVersion()}.jar`); } - constructJavaCommandArgsForPmd(fileList: string, classPathsForExternalRules: string[], rulesets: string): string[] { + constructJavaCommandArgsForPmd(fileList: string, classPathsForExternalRules: string[], rulesets: string, outfile: string): string[] { const classpath = classPathsForExternalRules.concat([`${PMD7_LIB}/*`]).join(path.delimiter); const args = ['-cp', classpath, PMD7_CLI_CLASS, 'check', '--file-list', fileList, - '--format', 'xml']; + '--format', 'xml', '-r', outfile]; if (rulesets.length > 0) { args.push('--rulesets', rulesets); } diff --git a/src/lib/pmd/PmdEngine.ts b/src/lib/pmd/PmdEngine.ts index a7c23acca..261663bd2 100644 --- a/src/lib/pmd/PmdEngine.ts +++ b/src/lib/pmd/PmdEngine.ts @@ -147,15 +147,20 @@ abstract class AbstractPmdEngine extends AbstractRuleEngine { this.logger.trace('No matching pmd target files found. Nothing to execute.'); return []; } + const fh = new FileHandler(); + const reportFile: string = await fh.tmpFileWithCleanup(); this.logger.trace(`About to run PMD rules. Targets: ${targetPaths.length}, Selected rules: ${selectedRules}`); const stdout = await (await PmdWrapper.create({ targets: targetPaths, rules: selectedRules, rulePathsByLanguage, - supplementalClasspath + supplementalClasspath, + reportFile })).execute(); - const results = this.processStdOut(stdout); + this.logger.trace(`STDOUT from PMD: ${stdout}`); + const rawResults: string = await fh.readFile(reportFile); + const results = this.processOutput(rawResults); this.logger.trace(`Found ${results.length} for PMD`); return results; } catch (e) { @@ -167,21 +172,21 @@ abstract class AbstractPmdEngine extends AbstractRuleEngine { /** - * stdout returned from PMD contains an XML payload that may be surrounded by other text. + * PMD output is represented as an XML payload. * 'file' nodes from the XML are returned as rows of output to the user. 'configerror', 'error', * and 'suppressedviolation' nodes are emitted as warnings from the CLI. */ - protected processStdOut(stdout: string): RuleResult[] { + protected processOutput(output: string): RuleResult[] { let results: RuleResult[] = []; - this.logger.trace(`Output received from PMD: ${stdout}`); + this.logger.trace(`Output received from PMD: ${output}`); // Try to find the xml payload. It begins with '' const pmdEnd = ''; - const xmlStart = stdout.indexOf(' { @@ -56,7 +59,7 @@ export default class PmdWrapper extends PmdSupport { const pmdCommandInfo: PmdCommandInfo = Controller.getActivePmdCommandInfo(); const classPathsForExternalRules: string[] = this.buildSharedClasspath().concat(this.supplementalClasspath); - const args: string[] = pmdCommandInfo.constructJavaCommandArgsForPmd(tmpPath, classPathsForExternalRules, this.rules); + const args: string[] = pmdCommandInfo.constructJavaCommandArgsForPmd(tmpPath, classPathsForExternalRules, this.rules, this.reportFile); this.logger.trace(`Preparing to execute PMD with command: "${command}", args: "${JSON.stringify(args)}"`); return [command, args]; diff --git a/test/lib/pmd/PmdEngine.test.ts b/test/lib/pmd/PmdEngine.test.ts index a600d5ce5..9866bf8ff 100644 --- a/test/lib/pmd/PmdEngine.test.ts +++ b/test/lib/pmd/PmdEngine.test.ts @@ -37,7 +37,7 @@ describe('Tests for BasePmdEngine and PmdEngine implementation', () => { afterEach(() => { Sinon.restore(); }); - describe('processStdOut()', () => { + describe('processOutput()', () => { it('Nodes that do not represent violations are filtered out of results', async () => { // This file contains a `file`-type node and a mix of other node types that are direct children of the `pmd` // node. The file nodes and the error nodes representing parser errors should be converted to violations. @@ -47,7 +47,7 @@ describe('Tests for BasePmdEngine and PmdEngine implementation', () => { const xml: string = await fileHandler.readFile(xmlPath); expect(xml).to.not.be.null; - const results = (testPmdEngine as any).processStdOut(xml); + const results = (testPmdEngine as any).processOutput(xml); expect(results).to.be.length(3, 'Should be three result entries'); expect(results[0].violations).to.be.length(13, 'Unexpected violation count in 1st entry'); expect(results[1].violations).to.be.length(1, 'Unexpected violation count in 2nd entry'); @@ -94,7 +94,7 @@ describe('Tests for BasePmdEngine and PmdEngine implementation', () => { const xml: string = await fileHandler.readFile(xmlPath); expect(xml).to.not.be.null; - await (testPmdEngine as any).processStdOut(xml); + await (testPmdEngine as any).processOutput(xml); Sinon.assert.callCount(uxSpy, 3); Sinon.assert.calledWith(uxSpy, EVENTS.WARNING_ALWAYS, expectedConfigError); Sinon.assert.calledWith(uxSpy, EVENTS.WARNING_ALWAYS, expectedError); @@ -193,19 +193,19 @@ describe('Tests for BasePmdEngine and PmdEngine implementation', () => { describe('processStdout unusual cases', () => { it('Empty stdout', async () => { - const results = await (testPmdEngine as any).processStdOut(''); + const results = await (testPmdEngine as any).processOutput(''); expect(results).to.be.not.null; expect(results).to.be.lengthOf(0); }); it('Missing closing tag', async () => { - const results = await (testPmdEngine as any).processStdOut(' { - const results = await (testPmdEngine as any).processStdOut('blah blah blah'); + const results = await (testPmdEngine as any).processOutput('blah blah blah'); expect(results).to.be.not.null; expect(results).to.be.lengthOf(0); }); From 981b7033db439216ded1204541d6c27d70c336c3 Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Wed, 24 Jul 2024 14:28:54 -0400 Subject: [PATCH 07/14] Upgrade pmd-appexchange rules to 0.14 --- .../docs/AvoidCreateElementScriptLinkTag.md | 4 +++- .../docs/AvoidDisableProtocolSecurity.md | 18 ++++++++++++++++++ .../docs/AvoidHardCodedCredentialsInAura.md | 18 ++++++++++++++++++ .../docs/AvoidHardCodedSecretsInVFAttrs.md | 18 ++++++++++++++++++ .../AvoidInsecureHttpRemoteSiteSetting.md | 18 ++++++++++++++++++ pmd-appexchange/docs/AvoidSControls.md | 18 ++++++++++++++++++ pmd-appexchange/docs/AvoidUnescapedHtml.md | 18 ++++++++++++++++++ pmd-appexchange/lib/pmd-aura-html-sf-0.1.jar | Bin 0 -> 2843 bytes .../lib/pmd-customrules-utils-0.0.1.jar | Bin 4112 -> 0 bytes .../lib/pmd-customrules-utils-0.1.jar | Bin 0 -> 4431 bytes ...-0.0.1.jar => sf_metadata_pmd_xml-0.1.jar} | Bin 3468 -> 3468 bytes ...d-apex-0.13.jar => sfca-pmd-apex-0.14.jar} | Bin 35725 -> 35870 bytes .../lib/sfca-pmd-aurahtml-0.14.jar | Bin 0 -> 6254 bytes ...d-html-0.13.jar => sfca-pmd-html-0.14.jar} | Bin 1910 -> 1910 bytes ...-0.13.jar => sfca-pmd-javascript-0.14.jar} | Bin 1941 -> 1941 bytes .../lib/sfca-pmd-sfmetadata-0.13.jar | Bin 3539 -> 0 bytes .../lib/sfca-pmd-sfmetadata-0.14.jar | Bin 0 -> 3746 bytes ...0.13.jar => sfca-pmd-visualforce-0.14.jar} | Bin 15327 -> 18142 bytes pmd-appexchange/lib/sfca-pmd-xml-0.13.jar | Bin 6772 -> 0 bytes pmd-appexchange/lib/sfca-pmd-xml-0.14.jar | Bin 0 -> 6843 bytes src/Constants.ts | 2 +- src/lib/pmd/PmdEngine.ts | 2 +- 22 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 pmd-appexchange/docs/AvoidDisableProtocolSecurity.md create mode 100644 pmd-appexchange/docs/AvoidHardCodedCredentialsInAura.md create mode 100644 pmd-appexchange/docs/AvoidHardCodedSecretsInVFAttrs.md create mode 100644 pmd-appexchange/docs/AvoidInsecureHttpRemoteSiteSetting.md create mode 100644 pmd-appexchange/docs/AvoidSControls.md create mode 100644 pmd-appexchange/docs/AvoidUnescapedHtml.md create mode 100644 pmd-appexchange/lib/pmd-aura-html-sf-0.1.jar delete mode 100644 pmd-appexchange/lib/pmd-customrules-utils-0.0.1.jar create mode 100644 pmd-appexchange/lib/pmd-customrules-utils-0.1.jar rename pmd-appexchange/lib/{pmd-xml-sf-0.0.1.jar => sf_metadata_pmd_xml-0.1.jar} (62%) rename pmd-appexchange/lib/{sfca-pmd-apex-0.13.jar => sfca-pmd-apex-0.14.jar} (68%) create mode 100644 pmd-appexchange/lib/sfca-pmd-aurahtml-0.14.jar rename pmd-appexchange/lib/{sfca-pmd-html-0.13.jar => sfca-pmd-html-0.14.jar} (53%) rename pmd-appexchange/lib/{sfca-pmd-javascript-0.13.jar => sfca-pmd-javascript-0.14.jar} (53%) delete mode 100644 pmd-appexchange/lib/sfca-pmd-sfmetadata-0.13.jar create mode 100644 pmd-appexchange/lib/sfca-pmd-sfmetadata-0.14.jar rename pmd-appexchange/lib/{sfca-pmd-visualforce-0.13.jar => sfca-pmd-visualforce-0.14.jar} (52%) delete mode 100644 pmd-appexchange/lib/sfca-pmd-xml-0.13.jar create mode 100644 pmd-appexchange/lib/sfca-pmd-xml-0.14.jar diff --git a/pmd-appexchange/docs/AvoidCreateElementScriptLinkTag.md b/pmd-appexchange/docs/AvoidCreateElementScriptLinkTag.md index 38dd0388f..0e07ad64a 100644 --- a/pmd-appexchange/docs/AvoidCreateElementScriptLinkTag.md +++ b/pmd-appexchange/docs/AvoidCreateElementScriptLinkTag.md @@ -10,7 +10,9 @@ AvoidCreateElementScriptLinkTag[](#avoidcreateelementscriptlinktag) **Description:** - Detects dynamic creation of script or link tags +Detects dynamic creation of script or link tags +Note: This rule identifies the ` - + + Salesforce Code Analyzer Report

Salesforce Code Analyzer Report

-
+

@@ -319,7 +320,7 @@ End Column - +
From ba52f4de7219b02b73d9f793beed21c7d816dbbe Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Mon, 29 Jul 2024 10:27:23 -0400 Subject: [PATCH 13/14] Fix eslint warnings --- .eslintrc.json | 5 ++++- src/commands/scanner/rule/add.ts | 1 + src/commands/scanner/rule/describe.ts | 1 + src/commands/scanner/rule/list.ts | 1 + src/commands/scanner/rule/remove.ts | 1 + src/lib/ScannerRunCommand.ts | 1 + 6 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 28a3ed529..2130f6b45 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -13,5 +13,8 @@ }, "plugins": [ "@typescript-eslint" - ] + ], + "rules": { + "sf-plugin/only-extend-SfCommand": "off" + } } diff --git a/src/commands/scanner/rule/add.ts b/src/commands/scanner/rule/add.ts index bbedb40f3..1851f1b77 100644 --- a/src/commands/scanner/rule/add.ts +++ b/src/commands/scanner/rule/add.ts @@ -20,6 +20,7 @@ export default class Add extends ScannerCommand { // This defines the flags accepted by this command. The key is the longname, the char property is the shortname, // and summary and description is what's printed when the -h/--help flag is supplied. public static readonly flags = { + ...ScannerCommand.flags, language: Flags.string({ char: 'l', summary: getMessage(BundleName.Add, 'flags.languageSummary'), diff --git a/src/commands/scanner/rule/describe.ts b/src/commands/scanner/rule/describe.ts index 20841ff92..e90547cb1 100644 --- a/src/commands/scanner/rule/describe.ts +++ b/src/commands/scanner/rule/describe.ts @@ -19,6 +19,7 @@ export default class Describe extends ScannerCommand { // This defines the flags accepted by this command. The key is the longname, the char property is the shortname, // and summary and description is what's printed when the -h/--help flag is supplied. public static readonly flags = { + ...ScannerCommand.flags, rulename: Flags.string({ char: 'n', summary: getMessage(BundleName.Describe, 'flags.rulenameSummary'), diff --git a/src/commands/scanner/rule/list.ts b/src/commands/scanner/rule/list.ts index 0af1b6fee..fd3b9326c 100644 --- a/src/commands/scanner/rule/list.ts +++ b/src/commands/scanner/rule/list.ts @@ -22,6 +22,7 @@ export default class List extends ScannerCommand { // This defines the flags accepted by this command. The key is the longname, the char property is the shortname, // and summary and description is what's printed when the -h/--help flag is supplied. public static readonly flags = { + ...ScannerCommand.flags, verbose: Flags.boolean({ summary: getMessage(BundleName.Common, 'flags.verboseSummary') }), diff --git a/src/commands/scanner/rule/remove.ts b/src/commands/scanner/rule/remove.ts index 81f374a5e..52fcb3bc6 100644 --- a/src/commands/scanner/rule/remove.ts +++ b/src/commands/scanner/rule/remove.ts @@ -21,6 +21,7 @@ export default class Remove extends ScannerCommand { // This defines the flags accepted by this command. The key is the longname, the char property is the shortname, // and summary and description is what's printed when the -h/--help flag is supplied. public static readonly flags = { + ...ScannerCommand.flags, verbose: Flags.boolean({ summary: getMessage(BundleName.Common, 'flags.verboseSummary') }), diff --git a/src/lib/ScannerRunCommand.ts b/src/lib/ScannerRunCommand.ts index b57d59bf0..43ff08896 100644 --- a/src/lib/ScannerRunCommand.ts +++ b/src/lib/ScannerRunCommand.ts @@ -9,6 +9,7 @@ export abstract class ScannerRunCommand extends ScannerCommand { * here to avoid duplicate code. */ public static readonly flags = { + ...ScannerCommand.flags, verbose: Flags.boolean({ summary: getMessage(BundleName.Common, 'flags.verboseSummary') }), From f26eaee83aee30f1f1b1f68be1c3e03253dab3bc Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Mon, 29 Jul 2024 10:32:30 -0400 Subject: [PATCH 14/14] Fix create release branch script --- .github/workflows/create-release-branch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create-release-branch.yml b/.github/workflows/create-release-branch.yml index f6d95b29a..c61678367 100644 --- a/.github/workflows/create-release-branch.yml +++ b/.github/workflows/create-release-branch.yml @@ -145,7 +145,7 @@ jobs: git checkout -b release-$NEW_VERSION git push --set-upstream origin release-$NEW_VERSION # Now that we're done with the interim branch, delete it. - git push -d ${NEW_VERSION}-interim + git push -d origin ${NEW_VERSION}-interim # Output the release branch name so we can use it in later jobs. echo "branch_name=release-$NEW_VERSION" >> "$GITHUB_OUTPUT" # Run all the various tests against the newly created branch.