From 4eeffcf911f4d94719f659a652dcbe27ea53a3e8 Mon Sep 17 00:00:00 2001 From: Nicolas Vuillamy Date: Mon, 26 Feb 2024 16:07:20 +0100 Subject: [PATCH 1/4] v0 --- defaults/ci/.prettierrc | 17 ++++ .../hardis/project/configure/cloudiscore.ts | 89 +++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 defaults/ci/.prettierrc create mode 100644 src/commands/hardis/project/configure/cloudiscore.ts diff --git a/defaults/ci/.prettierrc b/defaults/ci/.prettierrc new file mode 100644 index 000000000..18039a031 --- /dev/null +++ b/defaults/ci/.prettierrc @@ -0,0 +1,17 @@ +{ + "trailingComma": "none", + "plugins": [ + "prettier-plugin-apex", + "@prettier/plugin-xml" + ], + "overrides": [ + { + "files": "**/lwc/**/*.html", + "options": { "parser": "lwc" } + }, + { + "files": "*.{cmp,page,component}", + "options": { "parser": "html" } + } + ] +} diff --git a/src/commands/hardis/project/configure/cloudiscore.ts b/src/commands/hardis/project/configure/cloudiscore.ts new file mode 100644 index 000000000..7fdb7208e --- /dev/null +++ b/src/commands/hardis/project/configure/cloudiscore.ts @@ -0,0 +1,89 @@ +/* jscpd:ignore-start */ +import { flags, SfdxCommand } from "@salesforce/command"; +import { Messages, SfdxError } from "@salesforce/core"; +import { AnyJson } from "@salesforce/ts-types"; +import * as c from "chalk"; +import * as fs from "fs-extra"; +import * as path from "path"; +import { uxLog } from "../../../../common/utils"; +import { PACKAGE_ROOT_DIR } from "../../../../settings"; + +// Initialize Messages with the current plugin directory +Messages.importMessagesDirectory(__dirname); + +// Load the specific messages for this file. Messages from @salesforce/command, @salesforce/core, +// or any library that is using the messages framework can also be loaded this way. +const messages = Messages.loadMessages("sfdx-hardis", "org"); + +export default class ConfigureCloudiscore extends SfdxCommand { + public static title = "Configure SFDX Project local files"; + + public static description = "Configure sfdx project for CloudiScore"; + + public static examples = ["$ sfdx hardis:project:configure:localconfig"]; + + // public static args = [{name: 'file'}]; + + protected static flagsConfig = { + debug: flags.boolean({ + char: "d", + default: false, + description: messages.getMessage("debugMode"), + }), + websocket: flags.string({ + description: messages.getMessage("websocket"), + }), + skipauth: flags.boolean({ + description: "Skip authentication check when a default username is required", + }), + }; + + // Comment this out if your command does not require an org username + protected static supportsUsername = true; + protected static requiresUsername = false; + + // Comment this out if your command does not support a hub org username + protected static supportsDevhubUsername = true; + protected static requiresDevhubUsername = false; + + // Set this to true if your command requires a project workspace; 'requiresProject' is false by default + protected static requiresProject = true; + /* jscpd:ignore-end */ + + public async run(): Promise { + + // Default files (without overwrite) + await fs.copy(path.join(PACKAGE_ROOT_DIR, "defaults/ci", "."), process.cwd(), { overwrite: false }); + uxLog(this, c.gray("Copied config files")); + + // Package.sjon + const packageJsonFile = path.join(process.cwd(), "package.json"); + if (!fs.existsSync(packageJsonFile)) { + throw new SfdxError("You need to be at the root of a SFDX project with a package.json file"); + } + const packageJson = JSON.parse(fs.readFileSync(packageJsonFile, { encoding: "utf8" }).toString()); + + const scripts = { + "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,page,trigger}\"", + "prettier:verify": "prettier --check \"**/*.{cls,cmp,component,css,html,js,page,trigger}\"", + "postinstall": "rm -rf .git/hooks" + } + packageJson.scripts = Object.assign(packageJson.scripts || {}, scripts); + packageJson["lint-staged"] = {}; + + await fs.writeFile(packageJsonFile, JSON.stringify(packageJson, null, 2)); + uxLog(this, c.gray("Updated package.json file to have CloudiScore configuration")); + + // Prettier + const prettierRcJsonFile = path.join(process.cwd(), ".prettierrc"); + const prettierRcJson = JSON.parse(fs.readFileSync(prettierRcJsonFile, { encoding: "utf8" }).toString()); + prettierRcJson.printWidth = 120; + await fs.writeFile(prettierRcJsonFile, JSON.stringify(prettierRcJson, null, 2)); + uxLog(this, c.gray("Updated .prettierrc file to have CloudiScore configuration")); + + uxLog(this, c.green(`Now you can run command ${c.bold("npm install")}`)); + + // Return an object to be displayed with --json + return { outputString: "Configured project for CloudiScore" }; + } +} From 166f5cf0720928c6283842e78d3f5cb5310eb7db Mon Sep 17 00:00:00 2001 From: Nicolas Vuillamy Date: Mon, 11 Mar 2024 17:33:49 +0100 Subject: [PATCH 2/4] Quality --- defaults/ci/.eslintignore | 3 +++ defaults/ci/.prettierignore | 11 +++++++++++ .../project/configure/{cloudiscore.ts => quality.ts} | 10 ++++++---- 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 defaults/ci/.eslintignore create mode 100644 defaults/ci/.prettierignore rename src/commands/hardis/project/configure/{cloudiscore.ts => quality.ts} (88%) diff --git a/defaults/ci/.eslintignore b/defaults/ci/.eslintignore new file mode 100644 index 000000000..3c95b8e09 --- /dev/null +++ b/defaults/ci/.eslintignore @@ -0,0 +1,3 @@ +node_modules +lib +ref \ No newline at end of file diff --git a/defaults/ci/.prettierignore b/defaults/ci/.prettierignore new file mode 100644 index 000000000..8cccc6e59 --- /dev/null +++ b/defaults/ci/.prettierignore @@ -0,0 +1,11 @@ +# List files or directories below to ignore them when running prettier +# More information: https://prettier.io/docs/en/ignore.html +# + +**/staticresources/** +.localdevserver +.sfdx +.sf +.vscode + +coverage/ \ No newline at end of file diff --git a/src/commands/hardis/project/configure/cloudiscore.ts b/src/commands/hardis/project/configure/quality.ts similarity index 88% rename from src/commands/hardis/project/configure/cloudiscore.ts rename to src/commands/hardis/project/configure/quality.ts index 7fdb7208e..1bb356f15 100644 --- a/src/commands/hardis/project/configure/cloudiscore.ts +++ b/src/commands/hardis/project/configure/quality.ts @@ -15,12 +15,12 @@ Messages.importMessagesDirectory(__dirname); // or any library that is using the messages framework can also be loaded this way. const messages = Messages.loadMessages("sfdx-hardis", "org"); -export default class ConfigureCloudiscore extends SfdxCommand { +export default class ConfigureQuality extends SfdxCommand { public static title = "Configure SFDX Project local files"; - public static description = "Configure sfdx project for CloudiScore"; + public static description = "Configure sfdx project for Quality Checks"; - public static examples = ["$ sfdx hardis:project:configure:localconfig"]; + public static examples = ["$ sfdx hardis:project:configure:quality"]; // public static args = [{name: 'file'}]; @@ -81,7 +81,9 @@ export default class ConfigureCloudiscore extends SfdxCommand { await fs.writeFile(prettierRcJsonFile, JSON.stringify(prettierRcJson, null, 2)); uxLog(this, c.gray("Updated .prettierrc file to have CloudiScore configuration")); - uxLog(this, c.green(`Now you can run command ${c.bold("npm install")}`)); + uxLog(this, c.green(`Now you can run command ${c.bold("npm install")} to install local dependencies`)); + + uxLog(this, c.yellow(`Before running ${c.bold("npm run prettier")}, make sure to add imported/generated code in ${c.bold(".prettierignore")} and ${c.bold(".eslintignore")} files !`)); // Return an object to be displayed with --json return { outputString: "Configured project for CloudiScore" }; From 7d83313f345f32f79089065e757746186ee95fa3 Mon Sep 17 00:00:00 2001 From: Nicolas Vuillamy Date: Mon, 11 Mar 2024 20:15:53 +0100 Subject: [PATCH 3/4] Comments --- src/commands/hardis/project/configure/quality.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/commands/hardis/project/configure/quality.ts b/src/commands/hardis/project/configure/quality.ts index 1bb356f15..2ec75a570 100644 --- a/src/commands/hardis/project/configure/quality.ts +++ b/src/commands/hardis/project/configure/quality.ts @@ -81,9 +81,12 @@ export default class ConfigureQuality extends SfdxCommand { await fs.writeFile(prettierRcJsonFile, JSON.stringify(prettierRcJson, null, 2)); uxLog(this, c.gray("Updated .prettierrc file to have CloudiScore configuration")); - uxLog(this, c.green(`Now you can run command ${c.bold("npm install")} to install local dependencies`)); - - uxLog(this, c.yellow(`Before running ${c.bold("npm run prettier")}, make sure to add imported/generated code in ${c.bold(".prettierignore")} and ${c.bold(".eslintignore")} files !`)); + uxLog(this, c.green("What's next ?")); + uxLog(this, c.green(`- Run command ${c.bold("npm install")} to install local dependencies`)); + uxLog(this, c.yellow(`- Discard updated GitHub/GitLab/Azure/Bitbucket CI/CD items that you are not using`)); + uxLog(this, c.yellow(`- Add exceptions in ${c.bold(".prettierignore")} and ${c.bold(".eslintignore")} to ignore generated or imported Apex/LWC files`)); + uxLog(this, c.yellow(`- Create a first commit, so you can discard later in case you forgot prettier / eslint exceptions`)); + uxLog(this, c.green(`- Run ${c.bold("npm run prettier")} to apply formatting on files`)); // Return an object to be displayed with --json return { outputString: "Configured project for CloudiScore" }; From 31ed3541002e11c212e7cb549e9fdffdd31959d3 Mon Sep 17 00:00:00 2001 From: Nicolas Vuillamy Date: Tue, 30 Apr 2024 10:06:22 +0200 Subject: [PATCH 4/4] prompt for apex pmd ruleset level --- .../hardis/project/configure/quality.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/commands/hardis/project/configure/quality.ts b/src/commands/hardis/project/configure/quality.ts index 2ec75a570..59abf7065 100644 --- a/src/commands/hardis/project/configure/quality.ts +++ b/src/commands/hardis/project/configure/quality.ts @@ -7,6 +7,7 @@ import * as fs from "fs-extra"; import * as path from "path"; import { uxLog } from "../../../../common/utils"; import { PACKAGE_ROOT_DIR } from "../../../../settings"; +import { prompts } from "../../../../common/utils/prompts"; // Initialize Messages with the current plugin directory Messages.importMessagesDirectory(__dirname); @@ -81,6 +82,25 @@ export default class ConfigureQuality extends SfdxCommand { await fs.writeFile(prettierRcJsonFile, JSON.stringify(prettierRcJson, null, 2)); uxLog(this, c.gray("Updated .prettierrc file to have CloudiScore configuration")); + // PMD Ruleset Selection + const promptsPmdLevel = await prompts( + { + type: "select", + name: "pmdLevelFile", + message: "Please select the PMD ruleset level", + choices: [ + { title: "High quality", description: "Use for a new BUILD project", value: "pmd-ruleset-high.xml" }, + { title: "Medium quality", description: "Use to improve the quality of a RUN project", value: "pmd-ruleset-medium.xml" }, + { title: "Low quality", description: "Use for RUN project", value: "pmd-ruleset.xml" }, + ], + }, + ); + const pmdLevelFile = promptsPmdLevel.pmdLevelFile; + const pmdRuleSetFileSource = path.join(PACKAGE_ROOT_DIR, "config", pmdLevelFile); + const pmdRuleSetFileTarget = path.join(process.cwd(), "config", "pmd-ruleset.xml"); + await fs.copy(pmdRuleSetFileSource, pmdRuleSetFileTarget, { overwrite: true }); + uxLog(this, c.gray(`Imported PMD rules file ${c.bold(pmdLevelFile)} into config/pmd-ruleset.xml`)); + uxLog(this, c.green("What's next ?")); uxLog(this, c.green(`- Run command ${c.bold("npm install")} to install local dependencies`)); uxLog(this, c.yellow(`- Discard updated GitHub/GitLab/Azure/Bitbucket CI/CD items that you are not using`));