Skip to content

Commit

Permalink
Merge pull request #1629 from forcedotcom/release-5.0.0-alpha.2
Browse files Browse the repository at this point in the history
RELEASE @W-16608399@: Conducting 5.0.0 alpha.2 release
  • Loading branch information
jag-j authored Sep 24, 2024
2 parents 91a1b37 + 822b2e9 commit 019a7d1
Show file tree
Hide file tree
Showing 70 changed files with 2,696 additions and 1,505 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ indent_size = 2
[*.kts]
indent_style = space
indent_size = 2

[*.goldfile]
insert_final_newline = false
18 changes: 18 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,21 @@ jobs:
path: |
./reports
./coverage
# For now, the smoke tests are no-ops, so the job doesn't have to do anything exciting.
# When smoke-tests stop being no-ops, we'll need a build-dependencies step to create a tarball artifact, and so forth.
# We'll be able to use the v4 workflow as a template.
smoke-tests:
strategy:
# By default, if any job in a matrix fails, all other jobs are automatically cancelled. This makes the jobs run
# to completion instead.
fail-fast: false
matrix:
node: ${{ fromJson(inputs.node-matrix) }}
os: [{vm: ubuntu-latest, exe: .sh}, {vm: macos-latest, exe: .sh}, {vm: windows-latest, exe: .cmd}]
runs-on: ${{ matrix.os.vm }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.target-branch }}
- run: smoke-tests/smoke-test${{ matrix.os.exe }} sf

37 changes: 19 additions & 18 deletions messages/config-command.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,37 @@ Display the current state of configuration for Code Analyzer.

# command.description

Code Analyzer gives you the ability to configure settings that modify Code Analyzer's behavior, to override the tags and severity levels of rules, and to configure the engine specific settings. Use this command to see the current state of this configuration and to save this state to a YAML-formatted file that you can modify to our needs.
Code Analyzer gives you the ability to configure settings that modify Code Analyzer's behavior, to override the tags and severity levels of rules, and to configure the engine specific settings. Use this command to see the current state of this configuration. You can also save this state to a YAML-formatted file that you can modify for your needs.

To apply a custom configuration with Code Analyzer, either keep your custom configuration settings in a 'code-analyzer.yml' file located in the current working directory from which you are executing commands, or specify the location of your custom configuration file to each of the Code Analyzer commands via the `--config-file` flag.
To apply a custom configuration with Code Analyzer, either keep your custom configuration settings in a `code-analyzer.yml` file located in the current folder from which you are executing commands, or specify the location of your custom configuration file to the Code Analyzer commands with the --config-file flag.

# command.examples

- Display the current state of configuration for Code Analyzer using the default behavior: display top level configuration, display the engine and rule override settings associated with all the rules that have a 'Recommended' tag; and automatically apply any existing custom configuration settings found in a "code-analyzer.yml" or "code-analyzer.yaml" file in the current folder:
- Display the current state of the Code Analyzer configuration using the default behavior: display top level configuration, display the engine and rule override settings associated with all the rules that have a "Recommended" tag; and automatically apply any existing custom configuration settings found in a `code-analyzer.yml` or `code-analyzer.yaml` file in the current folder:

<%= config.bin %> <%= command.id %>
<%= config.bin %> <%= command.id %>

- This example is identical to the previous one, if `./code-analyzer.yml` exists.
- This example is identical to the previous one, assuming that `./code-analyzer.yml` exists in your current folder.

<%= config.bin %> <%= command.id %> --config-file ./code-analyzer.yml --rule-selector Recommended
<%= config.bin %> <%= command.id %> --config-file ./code-analyzer.yml --rule-selector Recommended

- Write the current state of configuration to `code-analyzer.yml`, including any configuration from an existing `code-analyzer.yml` file. This preserves all values from the original config, but will overwrite any comments:
- Write the current state of configuration to the file `code-analyzer.yml`, including any configuration from an existing `code-analyzer.yml` file. The command preserves all values from the original config, but overwrites any comments:

<%= config.bin %> <%= command.id %> --config-file ./code-analyzer.yml --output-file code-analyzer.yml
<%= config.bin %> <%= command.id %> --config-file ./code-analyzer.yml --output-file code-analyzer.yml

- Display the configuration state for all rules, instead of just the recommended ones:

<%= config.bin %> <%= command.id %> --rule-selector all
<%= config.bin %> <%= command.id %> --rule-selector all

- Display the configuration state associated with recommended rules that are applicable to your workspace folder, `./src`:

<%= config.bin %> <%= command.id %> --workspace ./src
<%= config.bin %> <%= command.id %> --workspace ./src

- Display any relevant configuration settings associated with the rule name 'no-undef' from the 'eslint' engine:

<%= config.bin %> <%= command.id %> --rule-selection eslint:no-undef
<%= config.bin %> <%= command.id %> --rule-selection eslint:no-undef

- Load from an existing configuration called 'existing-config.yml', but write to a new configuration file called 'new-config.yml' the configuration state that is applicable to all rules that are relevant to workspace located in current working directory:
- Load an existing configuration file called `existing-config.yml`, and then write the configuration to a new file called `new-config.yml`, the configuration state that is applicable to all rules that are relevant to the workspace located in the current folder:

<%= config.bin %> <%= command.id %> --config-file ./existing-config.yml --rule-selection all --workspace . --output-file ./subfolder-config.yml

Expand All @@ -43,11 +44,11 @@ Set of files you want to include in the code analysis.

# flags.workspace.description

If you specify this flag, the command returns a more accurate list of the rules that apply to the files that make up your workspace. Typically, a workspace is a single project folder that contains all your files. But it can also consist of one or more folders, one or more files, and use glob patterns (wildcards). If you specify this flag multiple times, then your workspace is the sum of the files and folders.
Use the --workspace flag to display only the configuration associated with the rules that apply to the files that make up your workspace. Typically, a workspace is a single project folder that contains all your files. But it can also consist of one or more folders, one or more files, and use glob patterns (wildcards). If you specify this flag multiple times, then your workspace is the sum of the files and folders.

This command uses the type of file in the workspace, such as JavaScript or Typescript, to determine the rules to list. For example, if your workspace contains only JavaScript files, the command doesn't list TypeScript rules. The command uses a file's extension to determine what kind of file it is, such as ".ts" for TypeScript.
This command uses the type of file in the workspace, such as JavaScript or Typescript, to determine the rules to include in the configuration state. For example, if your workspace contains only JavaScript files, the command doesn't include TypeScript rules. The command uses a file's extension to determine what kind of file it is, such as ".ts" for TypeScript.

Some engines may be configured to add additional rules based on what it finds in your workspace. For example, if you set the engines.eslint.auto_discover_eslint_config value of your code-analyzer.yml file to true, then supplying your workspace allows the "eslint" engine to examine your files in order to find ESLint configuration files that could potentially add in additional rules.
Some engines may be configured to add additional rules based on what it finds in your workspace. For example, if you set the "engines.eslint.auto_discover_eslint_config" value of your `code-analyzer.yml` file to true, then supplying your workspace allows the "eslint" engine to examine your files in order to find ESLint configuration files that could potentially add in additional rules.

# flags.rule-selector.summary

Expand All @@ -59,7 +60,7 @@ Use the --rule-selector flag to display only the configuration associated with t

You can combine different criteria using colons to further filter the list; the colon works as an intersection. For example, "--rule-selector eslint:Security" reduces the output to only contain the configuration state associated with the rules from the "eslint" engine that have the "Security" tag. To add multiple rule selectors together (a union), specify the --rule-selector flag multiple times, such as "--rule-selector eslint:Recommended --rule-selector retire-js:3".

If this flag is not specified, then the 'Recommended' tag rule selector will be used.
If you don't specify this flag, then the command uses the "Recommended" tag rule selector.

Run `<%= config.bin %> <%= command.id %> --rule-selector all` to display the configuration state associated with all possible rules available, and not just the recommended ones.

Expand All @@ -71,11 +72,11 @@ Path to the existing configuration file used to customize the engines and rules.

Use this flag to apply the customizations from a custom Code Analyzer configuration file to be displayed alongside the current Code Analyzer configuration state.

If this flag is not specified, then by default Code Analyzer will look for and apply a file named "code-analyzer.yml" or "code-analyzer.yaml" in your current working directory.
If you don't specify this flag, then the command looks for and applies a file named `code-analyzer.yml` or `code-analyzer.yaml` in your current folder.

# flags.output-file.summary

Output file to write the configuration state to. The file will be written in YAML format.
Output file to write the configuration state to. The file is written in YAML format.

# flags.output-file.description

Expand Down
14 changes: 14 additions & 0 deletions messages/config-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# template.last-calculated-as
Last calculated by the config command as: %s

# template.modified-from
Modified from: %s

# template.rule-overrides-section
%s ENGINE RULE OVERRIDES

# template.yaml.no-engines-selected
Empty object used because rule selection returned no rules

# template.yaml.no-rules-selected
Remove this empty object {} when you are ready to specify your first rule override
16 changes: 0 additions & 16 deletions messages/results-viewer.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# summary.found-no-results

Found 0 violations.

# summary.detail.found-results

Found %d violation(s) across %d file(s):
Expand All @@ -10,18 +6,6 @@ Found %d violation(s) across %d file(s):

%d. %s

# summary.detail.breakdown.header

Summary

# summary.detail.breakdown.total

Found %d violation(s):

# summary.detail.breakdown.item

%d %s severity

# summary.table.found-results

Found %d violation(s) across %d file(s) relative to '%s':
Expand Down
2 changes: 2 additions & 0 deletions messages/run-command.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ If you want to preview the list of rules before you actually run them, use the `

<%= config.bin %> <%= command.id %> --rule-selector eslint:getter-return --rule-selector no-inner-declarations

# command.examples.temporarily-hidden-for-now

- Specify three method starting points to be applied to the path-based recommended rules of the Salesforce Graph Engine, "sfge", while specifying the "./src" folder as the workspace to be used to build the source graph:

<%= config.bin %> <%= command.id %> --rule-selector sfge:Recommended --workspace ./src --path-start ./src/classes/Utils.cls#init --path-start ./src/classes/Helpers.cls#method1;method2
Expand Down
27 changes: 27 additions & 0 deletions messages/run-summary-viewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# summary.header

Summary

# summary.found-no-violations

Found 0 violations.

# summary.violations-total

Found %d violation(s):

# summary.violations-item

%d %s severity violation(s) found.

# summary.no-outfiles

No results files were specified.

# summary.outfiles-total

Results written to:

# summary.log-file-location

Additional log information written to:
7 changes: 7 additions & 0 deletions messages/shared.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# label.command-state

Developer Preview

# warning.command-state

This command is in %s.
17 changes: 10 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
{
"name": "@salesforce/plugin-code-analyzer",
"description": "Static code scanner that applies quality and security rules to Apex code, and provides feedback.",
"version": "5.0.0-alpha.1",
"version": "5.0.0-alpha.2",
"author": "Salesforce Code Analyzer Team",
"bugs": "https://github.com/forcedotcom/sfdx-scanner/issues",
"dependencies": {
"@oclif/core": "^3.3.2",
"@salesforce/code-analyzer-core": "0.12.0",
"@salesforce/code-analyzer-engine-api": "0.9.0",
"@salesforce/code-analyzer-eslint-engine": "0.9.0",
"@salesforce/code-analyzer-regex-engine": "0.9.0",
"@salesforce/code-analyzer-retirejs-engine": "0.9.0",
"@salesforce/code-analyzer-core": "^0.13.2",
"@salesforce/code-analyzer-engine-api": "0.10.0",
"@salesforce/code-analyzer-eslint-engine": "0.10.0",
"@salesforce/code-analyzer-pmd-engine": "0.10.1",
"@salesforce/code-analyzer-regex-engine": "0.10.0",
"@salesforce/code-analyzer-retirejs-engine": "0.10.0",
"@salesforce/core": "^5",
"@salesforce/sf-plugins-core": "^5.0.4",
"@salesforce/ts-types": "^2.0.9",
"@types/node": "^17",
"@types/js-yaml": "^4.0.9",
"@types/node": "^22.5.5",
"ansis": "^3.2.0",
"fast-glob": "^3.3.2",
"js-yaml": "^4.1.0",
"ts-node": "^10",
"tslib": "^2"
},
Expand Down
2 changes: 2 additions & 0 deletions smoke-tests/smoke-test-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ function generateScriptBody(isBash, delim) {
// Log an explainer that since we're in the Alpha stage, we don't have a fully fleshed out smoke test.
`echo "At this point in the alpha, the smoke tests are no-ops and it is fine."`
]

return commands.join('\n');
}

function generateScript(isBash, delim) {
Expand Down
4 changes: 2 additions & 2 deletions smoke-tests/smoke-test.cmd
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
@echo off
REM Auto-generated on Wed Aug 07 2024
REM Auto-generated on Tue Aug 27 2024
REM This script WILL EVENTUALLY run a smoke test of the entire plugin by running a series of commands that collectively
REM hit a vertical slice of all major features. If they all succeed, then we can reasonably assume that the plugin is
REM approximately stable.
REM DO NOT EDIT THIS SCRIPT DIRECTLY! INSTEAD, MAKE CHANGES IN ./smoke-tests/smoke-test-generator.js AND RERUN THAT
REM SCRIPT FROM THE PROJECT ROOT!
SET EXE_NAME=%1
undefined
echo "At this point in the alpha, the smoke tests are no-ops and it is fine."
4 changes: 2 additions & 2 deletions smoke-tests/smoke-test.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/bin/bash
# Auto-generated on Wed Aug 07 2024
# Auto-generated on Tue Aug 27 2024
# This script WILL EVENTUALLY run a smoke test of the entire plugin by running a series of commands that collectively
# hit a vertical slice of all major features. If they all succeed, then we can reasonably assume that the plugin is
# approximately stable.
# DO NOT EDIT THIS SCRIPT DIRECTLY! INSTEAD, MAKE CHANGES IN ./smoke-tests/smoke-test-generator.js AND RERUN THAT
# SCRIPT FROM THE PROJECT ROOT!
set -e
EXE_NAME=$1
undefined
echo "At this point in the alpha, the smoke tests are no-ops and it is fine."
32 changes: 14 additions & 18 deletions src/commands/code-analyzer/config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import {CodeAnalyzerConfig, RuleSelection} from "@salesforce/code-analyzer-core";
import {Flags, SfCommand} from '@salesforce/sf-plugins-core';
import {ConfigAction, ConfigDependencies} from '../../lib/actions/ConfigAction';
import {ConfigFileWriter} from '../../lib/writers/ConfigWriter';
import {ConfigRawYamlViewer} from '../../lib/viewers/ConfigViewer';
import {ConfigStyledYamlViewer} from '../../lib/viewers/ConfigViewer';
import {CodeAnalyzerConfigFactoryImpl} from '../../lib/factories/CodeAnalyzerConfigFactory';
import {EnginePluginsFactoryImpl} from '../../lib/factories/EnginePluginsFactory';
import {BundleName, getMessage, getMessages} from '../../lib/messages';
import {LogEventDisplayer} from '../../lib/listeners/LogEventListener';
import {RuleSelectionProgressSpinner} from '../../lib/listeners/ProgressEventListener';
import {DummyConfigModel} from '../../lib/models/ConfigModel';
import {AnnotatedConfigModel, ConfigContext} from '../../lib/models/ConfigModel';
import {Displayable, UxDisplay} from '../../lib/Display';

export default class ConfigCommand extends SfCommand<void> implements Displayable {
Expand All @@ -17,36 +16,31 @@ export default class ConfigCommand extends SfCommand<void> implements Displayabl
public static readonly summary = getMessage(BundleName.ConfigCommand, 'command.summary');
public static readonly description = getMessage(BundleName.ConfigCommand, 'command.description');
public static readonly examples = getMessages(BundleName.ConfigCommand, 'command.examples');
// TODO: UN-HIDE WHEN COMMAND IS READY
public static readonly hidden = true;

// TODO: Update when we go to Beta and when we go GA
public static readonly state = getMessage(BundleName.Shared, 'label.command-state');

public static readonly flags = {
workspace: Flags.string({
summary: getMessage(BundleName.ConfigCommand, 'flags.workspace.summary'),
description: getMessage(BundleName.ConfigCommand, 'flags.workspace.description'),
char: 'w',
multiple: true,
delimiter: ',',
// TODO: UN-HIDE WHEN ASSOCIATED FEATURES ARE IMPLEMENTED
hidden: true
delimiter: ','
}),
'rule-selector': Flags.string({
summary: getMessage(BundleName.ConfigCommand, 'flags.rule-selector.summary'),
description: getMessage(BundleName.ConfigCommand, 'flags.rule-selector.description'),
char: 'r',
multiple: true,
delimiter: ',',
default: ["Recommended"],
// TODO: UN-HIDE WHEN ASSOCIATED FEATURES ARE IMPLEMENTED
hidden: true
default: ["Recommended"]
}),
'config-file': Flags.file({
summary: getMessage(BundleName.ConfigCommand, 'flags.config-file.summary'),
description: getMessage(BundleName.ConfigCommand, 'flags.config-file.description'),
char: 'c',
exists: true,
// TODO: UN-HIDE WHEN ASSOCIATED FEATURES ARE IMPLEMENTED
hidden: true
exists: true
}),
'output-file': Flags.string({
summary: getMessage(BundleName.ConfigCommand, 'flags.output-file.summary'),
Expand All @@ -56,7 +50,9 @@ export default class ConfigCommand extends SfCommand<void> implements Displayabl
};

public async run(): Promise<void> {
this.warn('This command is still a work-in-progress. Currently it can only generate a fixed config file.');
// TODO: Update when we go to Beta and when we go GA
this.warn(getMessage(BundleName.Shared, "warning.command-state", [getMessage(BundleName.Shared, 'label.command-state')]));

const parsedFlags = (await this.parse(ConfigCommand)).flags;
const dependencies: ConfigDependencies = this.createDependencies(parsedFlags['output-file']);
const action: ConfigAction = ConfigAction.createAction(dependencies);
Expand All @@ -65,16 +61,16 @@ export default class ConfigCommand extends SfCommand<void> implements Displayabl

protected createDependencies(outputFile?: string): ConfigDependencies {
const uxDisplay: UxDisplay = new UxDisplay(this, this.spinner);
const modelGeneratorFunction = (rawConfig: CodeAnalyzerConfig, ruleSelection: RuleSelection) => {
return DummyConfigModel.fromSelection(rawConfig, ruleSelection);
const modelGeneratorFunction = (relevantEngines: Set<string>, userContext: ConfigContext, defaultContext: ConfigContext) => {
return AnnotatedConfigModel.fromSelection(relevantEngines, userContext, defaultContext);
};
const dependencies: ConfigDependencies = {
configFactory: new CodeAnalyzerConfigFactoryImpl(),
pluginsFactory: new EnginePluginsFactoryImpl(),
logEventListeners: [new LogEventDisplayer(uxDisplay)],
progressEventListeners: [new RuleSelectionProgressSpinner(uxDisplay)],
modelGenerator: modelGeneratorFunction,
viewer: new ConfigRawYamlViewer(uxDisplay)
viewer: new ConfigStyledYamlViewer(uxDisplay)
};
if (outputFile) {
dependencies.writer = ConfigFileWriter.fromFile(outputFile);
Expand Down
Loading

0 comments on commit 019a7d1

Please sign in to comment.