Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quality setup #587

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions defaults/ci/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
lib
ref
11 changes: 11 additions & 0 deletions defaults/ci/.prettierignore
Original file line number Diff line number Diff line change
@@ -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/
17 changes: 17 additions & 0 deletions defaults/ci/.prettierrc
Original file line number Diff line number Diff line change
@@ -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" }
}
]
}
114 changes: 114 additions & 0 deletions src/commands/hardis/project/configure/quality.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/* 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";
import { prompts } from "../../../../common/utils/prompts";

// 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 ConfigureQuality extends SfdxCommand {
public static title = "Configure SFDX Project local files";

public static description = "Configure sfdx project for Quality Checks";

public static examples = ["$ sfdx hardis:project:configure:quality"];

// 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<AnyJson> {

// 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"));

// 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`));
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" };
}
}
Loading