SFDX plugin to provide functionalities in order to improve and enhance your Development and CICD processes.
Table of Contents
- TL;DR
- Getting Started
- How to use it?
sfdx nps:coverage:formatters:mappaths -p <filepath> -t cobertura [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
sfdx nps:coverage:verify -p <filepath> [-r <number>] -c <string> [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
sfdx nps:package:destructive:versionobsoleteflows -p <filepath> [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
- Walkthrough
- Versioning
- Authors
- Contributing
- License
sfdx plugins:install nakama-plugin-sfdx
sfdx force:source:deploy --wait 60 --checkonly --manifest manifest/package.xml --testlevel RunLocalTests --junit --coverageformatters cobertura --resultsdir test-results --json > test-results/results.json
sfdx nps:coverage:verify --path test-results/results.json --required-coverage 90 --classes AccountTriggerHandler,ContactTriggerHandler
sfdx nps:package:destructive:versionobsoleteflows --path deltas/destructiveChanges/destructiveChanges.xml
Node v14.6.0 or above is required.
To check if Salesforce CLI runs under a supported node version for NPS, run sfdx --version
. You should see a node version above v.14.6.0. You should see a node version above v.14.6.0 to use NPS.
If you encounter this issue whereas the node version is OK on the running environment, try to install the Salesforce CLI via npm (npm install sfdx-cli --global
).
Nakama plugin SFDX is a Salesforce CLI plugin. Run the following command to install it:
sfdx plugins:install nakama-plugin-sfdx
Because this plugin is not signed, you will get a warning saying that "This plugin is not digitally signed and its authenticity cannot be verified". This is expected, and you will have to answer y
(yes) to proceed with the installation.
If you run your CI/CD jobs inside a Docker image, you can add the plugin to your image.
sfdx nps:coverage:formatters:mappaths -p <filepath> -t cobertura [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
sfdx nps:coverage:verify -p <filepath> -c <array> [-r <integer>] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
sfdx nps:package:destructive:versionobsoleteflows -p <filepath> [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
sfdx nps:coverage:formatters:mappaths -p <filepath> -t cobertura [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
Map the paths in a given file to replace them with the actual project relative location for classes and triggers.
USAGE
$ sfdx nps:coverage:formatters:mappaths -p <filepath> -t cobertura [--json] [--loglevel
trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
FLAGS
-p, --path=<value> (required) project relative path to
the file containing the test
execution results
-t, --type=(cobertura) (required) format type of the file
--json format output as json
--loglevel=(trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL) [default: warn] logging level for
this command invocation
DESCRIPTION
Map the paths in a given file to replace them with the actual project relative location for classes and triggers.
Known Limitations: - Currently it only supports verification of coverage for apex classes, but not apex triggers nor
flows.
EXAMPLES
$ sfdx nps:coverage:formatters:mappaths --path test-results/coverage/cobertura.xml --type cobertura
See code: src/commands/nps/coverage/formatters/mappaths.ts
sfdx nps:coverage:verify -p <filepath> -c <array> [-r <integer>] [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
Verifies that specified apex classes have a coverage above a certain treshold
USAGE
$ sfdx nps:coverage:verify -p <filepath> -c <array> [-r <integer>] [--json] [--loglevel
trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
FLAGS
-c, --classes=<value> (required) comma separated list of
apex classes to verify
-p, --path=<value> (required) project relative path to
the json file containing the test
execution results
-r, --required-coverage=<value> [default: 75] number of the
percentage of coverage treshold to
reach
--json format output as json
--loglevel=(trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL) [default: warn] logging level for
this command invocation
DESCRIPTION
Verifies that specified apex classes have a coverage above a certain treshold
EXAMPLES
$ sfdx nps:coverage:verify --path test-results/results.json --required-coverage 90 --classes AccountTriggerHandler,ContactTriggerHandler
See code: src/commands/nps/coverage/verify.ts
sfdx nps:package:destructive:versionobsoleteflows -p <filepath> [--json] [--loglevel trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
Replace the Flow members in a XML file by all the Obsolete flow versions in the default target org
USAGE
$ sfdx nps:package:destructive:versionobsoleteflows -p <filepath> [--json] [--loglevel
trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL]
FLAGS
-p, --path=<value> (required) project relative path to
the destructiveChange.xml
--json format output as json
--loglevel=(trace|debug|info|warn|error|fatal|TRACE|DEBUG|INFO|WARN|ERROR|FATAL) [default: warn] logging level for
this command invocation
DESCRIPTION
Replace the Flow members in a XML file by all the Obsolete flow versions in the default target org
EXAMPLES
$ sfdx nps:package:destructive:versionobsoleteflows --path deltas/destructiveChanges/destructiveChanges.xml
See code: src/commands/nps/package/destructive/versionobsoleteflows.ts
Let’s take a look at the following scenario:
Verify that each one of the non-test apex classes added or modified in a PR have a specific required coverage.
In our example, we have the following files:
- Flow deleted:
AccountFlow
- Custom Field added:
Account.NumberOfContacts__c
- Apex Class added:
ContactTriggerHandler
- Apex Class added:
ContactTriggerHandlerTest
- Apex Class modified:
AccountTriggerHandler
- Apex Class modified:
AccountTriggerHandlerTest
In this situation, we would expect the CLI plugin to:
- Handle the flow entries in
destructiveChanges.xml
for deletion:AccountFlow-1
- Detect the relevant apex classes in the PR to verify:
ContactTriggerHandler
,AccountTriggerHandler
- Report an error for those classes without enough test coverage:
AccountTriggerHandler
- Optional: if using Gitlab CI, highglight coverage in MR diff changes for:
ContactTriggerHandler
,AccountTriggerHandler
So let’s do it!
From the project repo folder, the CI pipeline will run the following command:
sfdx sgd:source:delta --source sfdx-source --from origin/$GITHUB_BASE_REF --to HEAD --output deltas --ignore .forceignore --generate-delta
See sfdx-git-delta
which means:
Analyze the differences between the PR targer branch and the source branch and create a folder ´deltas´ with all the modified and added files there.
Since flows can not be deleted with SFDX, what we actually want to delete is flow version:
sfdx nps:package:destructive:versionobsoleteflows --path deltas/destructiveChanges/destructiveChanges.xml
⚠️ This is still subjected to the restriction where a version needs to beInactive
for deletion
The simplest option to deploy the incremental changes is to use force:source:deploy
command with -x
parameter:
sfdx force:source:deploy --wait 60 --checkonly --manifest deltas/package/package.xml --postdestructivechanges deltas/destructiveChanges/destructiveChanges.xml --verbose --testlevel RunLocalTests --coverageformatters cobertura --resultsdir test-results --json > test-results/results.json
Optional, if using Gitlab CI: remap coverage formatter file with actual project locations paths for apex files
Due to the apex files actually belonging to an org, the coverage formatters uses apex files paths with a no-map/
default path. We can remap them properly to the real paths for the actual files location in our project with:
sfdx nps:coverage:formatters:mappaths -p test-results/cobertura.xml -t cobertura
⚠️ Currently there is a limitation where an issue will likely happen if there are.cls
and.trigger
files with the same name
(Bonus) Make sure that you specify the following in your deployment job:
artifacts:
when: always
reports:
coverage_report:
coverage_format: cobertura
path: test-results/coverage/cobertura.xml
Since deployment command output is captured into a file and does not appear in the job logs, it is recommented to print it with:
cat test-results/results.json
Now, we need to generate a comma separated list of the apex classes which coverage we want to check.
NON_TEST_CLASSES=$((egrep -wrliL @IsTest deltas --include \*.cls || echo "") | xargs -rL 1 basename | sed 's/.cls//g' | paste -sd "," -)
Imagine that you want all of our apex classes to have at least a 90% of test coverage. After running the previous commands, the remaining thing to do is:
sfdx nps:coverage:verify -p test-results/results.json -r 90 -c $NON_TEST_CLASSES
And voilà! 🥳
We should get and output like:
List of analyzed apex classes with coverage:
ContactTriggerHandler: 92%
AccountTriggerHandler: 68%
ERROR running nps:coverage:verify: Included apex classes should met at least the required coverage of 90%. Classes without enough coverage: AccountTriggerHandler
Besides, if using Gitlab CI and followe the optional steps, in our MR diff changes we should be able to spot the Test Coverage Visualization.
Versioning follows SemVer specification.
- Gabriel Serrano - Developer - jdkgabri
Contributions are what make the trailblazer community such an amazing place. I regard this component as a way to inspire and learn from others. Any contributions you make are appreciated.
This project license is MIT - see the LICENSE.md file for details