diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/404.html b/404.html new file mode 100644 index 000000000..d1d1b6057 --- /dev/null +++ b/404.html @@ -0,0 +1,7544 @@ + + + + + + + + + + + + + + + + + + + + + + + Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CHANGELOG/index.html b/CHANGELOG/index.html new file mode 100644 index 000000000..1d1897226 --- /dev/null +++ b/CHANGELOG/index.html @@ -0,0 +1,18519 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Changelog - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Changelog

+

[beta] (master)

+

Note: Can be used with sfdx plugins:install sfdx-hardis@beta and docker image hardisgroupcom/sfdx-hardis@beta

+
    +
  • New command hardis:doc:mkdocs-to-salesforce to generate static HTML doc and host it in a Static Resource and a VisualForce page
  • +
  • Remove hyperlinks from MermaidJs on Pull Request comments, to improve display on GitHub & Gitlab
  • +
  • Upgrade base image to python:3.12.8-alpine3.20, so mkdocs can be installed and run if necessary
  • +
+

[5.11.0] 2025-01-03

+ +
    +
  • New command hardis:project:deploy:notify to send Pull Request comments (with Flow Visual Git Diff) and Slack / Teams notifications even if you are not using a sfdx-hardis command to check or process a deployment.
  • +
+
    +
  • Command updates
      +
    • hardis:project:deploy:smart: Refactor deployment errors parsing: use JSON output instead of text output
    • +
    • hardis:org:test:apex: Display the number of failed tests in messages and notifications
    • +
    • hardis:org:monitor:backup:
        +
      • New option --exclude-namespaces that can be used with --full option
      • +
      • New option --full-apply-filters that can be used with --full option to apply filters anyway
      • +
      +
    • +
    +
  • +
+
    +
  • Core enhancements & fixes
      +
    • Obfuscate some data from text log files
    • +
    • Kill some exit handlers in case they are making the app crash after a throw SfError
    • +
    • Trigger notifications during the command execution, not after
    • +
    • Do not display warning in case no notification has been configured in case we are running locally
    • +
    • Fix Individual deployment tips markdown docs by adding quotes to YML properties
    • +
    • Fix init sfdx-hardis project commands and docs
    • +
    • Display warning message in case package.xml has wrong format
    • +
    • Allow to override package-no-overwrite from a branch .sfdx-hardis.yml config file
    • +
    • Using target_branch for Jira labels when isDeployBeforeMerge flag is true
    • +
    +
  • +
+
    +
  • Doc
      +
    • Update Microsoft Teams notifications integration User Guide
    • +
    • Add troubleshooting section in Email integration User Guide
    • +
    +
  • +
+

[5.10.1] 2024-12-12

+
    +
  • Fix sfdx-hardis docker image build by adding coreutils in dependencies
  • +
+

[5.10.0] 2024-12-12

+
    +
  • Update Docker base image to alpine to 3.21
  • +
+

[5.9.3] 2024-12-12

+
    +
  • hardis:org:data:import: Allow to run the command in production using, by either:
      +
    • Define sfdmuCanModify in your .sfdx-hardis.yml config file. (Example: sfdmuCanModify: prod-instance.my.salesforce.com)
    • +
    • Define an environment variable SFDMU_CAN_MODIFY. (Example: SFDMU_CAN_MODIFY=prod-instance.my.salesforce.com)
    • +
    +
  • +
+

[5.9.2] 2024-12-10

+
    +
  • Fallback message in case sfdx-hardis is not able to parse newest SF CLI errors format.
  • +
+

[5.9.1] 2024-12-09

+
    +
  • Fix issue that generates valid Pull Request comment whereas there is 1 error
  • +
  • Add TS test case
  • +
  • Upgrade NPM dependencies
  • +
+

[5.9.0] 2024-12-02

+
    +
  • hardis:org:monitor:backup: New mode --full, much slower than default filtered one, but that can retrieve ALL metadatas of an org
  • +
+

[5.8.1] 2024-11-26

+ +

[5.8.0] 2024-11-25

+ +

[5.7.2] 2024-11-25

+
    +
  • Fix issue with auth just before running a command (ask to run again the same command meanwhile we find a way to avoid that using SF CLI architecture)
  • +
+

[5.7.1] 2024-11-22

+
    +
  • In case a prompt is requested during CI and makes a command fail, display the content of the prompt
  • +
+

[5.7.0] 2024-11-22

+
    +
  • New command hardis:git:pull-requests:extract: Extract Pull Requests from Git Server into CSV/XLS (Azure only for now)
  • +
  • Fix bug when scratch org username is > 80 chars
  • +
  • Make markdown-links-check not blocking by default in MegaLinter base config
  • +
  • Make yamllint not blocking by default in MegaLinter base config
  • +
+

[5.6.3] 2024-11-17

+
    +
  • MegaLinter config: disable APPLY_FIXES by default
  • +
  • Upgrade npm dependencies
  • +
+

[5.6.2] 2024-11-12

+
    +
  • hardis:org:diagnose:unused-apex-classes
      +
    • Display class created by and created name MIN(date from org,date from git)
    • +
    • Replace errors by warnings, and add a message so users double-check before removing a class
    • +
    • Reorder console log
    • +
    +
  • +
  • Remove unused code from MetadataUtils class
  • +
+

[5.6.1] 2024-11-11

+
    +
  • Fix hardis:org:user:activateinvalid interactive mode
  • +
  • Update Dockerfile email address
  • +
  • Upgrade default Grafana Dashboards to add Unused Apex Classes indicator
  • +
  • Update hardis:org:diagnose:unused-apex-classes and hardis:doc:packagexml2markdown documentation
  • +
+

[5.6.0] 2024-11-09

+
    +
  • New command hardis:org:diagnose:unused-apex-classes, to detect Apex classes (Batch,Queueable,Schedulable) that has not been called for more than 365 days, that might be deleted to improve apex tests performances
  • +
  • hardis:doc:project2markdown: Update documentation
  • +
  • Polish CI/CD home doc
  • +
  • Refactor the build of hardis:org:monitor:all documentation
  • +
  • Fix issue with ToolingApi calls: handle paginated results instead of only the first 200 records.
  • +
+

[5.5.0] 2024-11-03

+
    +
  • hardis:doc:packagexml2markdown: Generate markdown documentation from a package.xml file
  • +
  • hardis:doc:project2markdown: Generate markdown documentation from any SFDX project (CI/CD, monitoring, projects not using sfdx-hardis...) in docs folder and add a link in README.md if existing.
  • +
  • hardis:org:monitor:backup: Call hardis:doc:project2markdown after backup
  • +
  • hardis:org:retrieve:packageconfig: Ignore standard Salesforce packages
  • +
  • Update CI/CD home documentation
  • +
+

[5.4.1] 2024-11-02

+
    +
  • hardis:org:multi-org-query enhancements
      +
    • Improve documentation
    • +
    • Allow to use --query-template as option to use one of the predefined templates via command line
    • +
    • Handle errors if issues when the command is called via a CI/CD job
    • +
    +
  • +
  • Upgrade dependencies
  • +
+

[5.4.0] 2024-11-02

+
    +
  • New command hardis:org:multi-org-query allowing to execute a SOQL Bulk Query in multiple orgs and aggregate the results in a single CSV / XLS report
  • +
  • New command hardis:org:community:update to Activate / Deactivate communities from command line
  • +
+

[5.3.0] 2024-10-24

+
    +
  • Update default Monitoring workflow for GitHub
  • +
  • Refactor file download code
      +
    • Display progress
    • +
    • Better error handling
    • +
    +
  • +
  • hardis:org:diagnose:legacyapi: Fix issue with big log files: Use stream to parse CSV and perform checks
  • +
  • Update default API version toto 62.0 (Winter 25 release)
  • +
+

[5.2.4] 2024-10-21

+
    +
  • Fix hardis:org:fix:listviewmine: Use chrome-launcher to find chrome executable to use with puppeteer-core
  • +
  • Remove keyv dependency
  • +
+

[5.2.3] 2024-10-19

+
    +
  • Change default .mega-linter.yml config
  • +
  • Display number of package.xml items before or after retrieving them
  • +
  • Doc: Update youtube preview images
  • +
+

[5.2.2] 2024-10-14

+
    +
  • Fix doubling -d option in hardis:scratch:create
  • +
+

[5.2.1] 2024-10-14

+
    +
  • 2 hardis commands: rename -d into something else when the short option was available twice on the same command
  • +
+

[5.2.0] 2024-10-14

+
    +
  • Improve BUILD & RUN documentation
  • +
  • 21 hardis commands: rename -o short into -f when possible, or other short letter, to avoid collision with -o (--target-org) option
  • +
  • Fix GitHub Org Monitoring workflow (remove push event + fix command typo)
  • +
+

[5.1.0] 2024-10-11

+
    +
  • hardis:project:deploy:smart: Fix to adapt stdout checks to output of sf project deploy start in case code coverage is ignored
  • +
  • hardis:org:monitor:backup: Allow spaces in folders
  • +
  • Remove pubsub from default .forceignore
  • +
  • Change default deployment waiting time from 60mn to 120mn
  • +
  • Display explicit warning message before ConnectedApp deployment so users don't forget to manually create the connected app with the certificate
  • +
+

[5.0.10] 2024-10-03

+
    +
  • hardis:project:deploy:smart : Fix parsing of error strings
  • +
  • hardis:project:deploy:smart : Fix markdown display on PR summary
  • +
+

[5.0.9] 2024-10-03

+
    +
  • Fix link to tip doc from Pull Request / Merge Request comments
  • +
  • Fixing small issues with creating scratch org and scratch org pool
  • +
+

[5.0.8] 2024-10-01

+
    +
  • Monitoring config: Fix way to define how to upload connected app
  • +
  • New deployment tip: Couldn't retrieve or load information on the field
  • +
  • Fix parsing of errors when they are unknown
  • +
  • Fix SEO info in deployment tips documentation
  • +
+

[5.0.7] 2024-09-25

+
    +
  • hardis:org:monitoring:backup : fix issue when metadata type is unknown
  • +
+

[5.0.6] 2024-09-25

+
    +
  • Allow to purge flows & flow interviews using --no-prompt option
  • +
  • Fix duplicate -f short option by replacing delete-flow-interviews short by -w
  • +
+

[5.0.5] 2024-09-24

+
    +
  • When git add / stash failure, display a message explaining to run git config --system core.longpaths true to solve the issue.
  • +
  • Improve test classes errors collection during deployment check
  • +
  • Display the number of elements deployed within a package.xml
  • +
+

[5.0.4] 2024-09-24

+
    +
  • Fix errors collection during deployment check
  • +
  • Display in deployment check summary when useSmartDeploymentTests has been activated
  • +
  • Do not send coverage formatters options when test level is NoTestRun
  • +
+

[5.0.3] 2024-09-23

+
    +
  • Add --ignore-conflicts to smartDeploy
  • +
+

[5.0.2] 2024-09-23

+
    +
  • Always use project deploy start --dry-run for deployment validation, until command project deploy validate works with --ignore-warnings & NoTestRun
  • +
+

[5.0.0] 2024-09-23

+

Refactoring explanations

+

The future deprecation of sfdx force:source:** commands on 6 november finally convinced us to switch everything from SFDX core to SF CLI core. (otherwise existing CI/CD pipelines would not work anymore from this date !)

+

Therefore, sfdx-hardis required a complete refactoring as described below, but this won't impact existing CI/CD and Monitoring pipelines.

+

We made many tests but risk zero do not exist, so if you see any bug, please report them ASAP and we'll solve them quickly :)

+

Major changes

+ +
    +
  • +

    Change background calls to legacy sfdx commands to call their SF Cli replacements

    +
      +
    • sfdx force:mdapi:convert -> sf project convert mdapi
    • +
    • sfdx force:mdapi:deploy -> sf project deploy start --metadata-dir
    • +
    • sfdx force:source:retrieve -> sf project retrieve start
    • +
    • sfdx force:source:deploy -> sf project deploy start
    • +
    • sfdx force:source:pull -> sf project retrieve start
    • +
    • sfdx force:source:push -> sf project deploy start
    • +
    • sfdx force:source:tracking:clear -> sf project delete tracking
    • +
    • sfdx force:source:manifest:create -> sf project generate manifest
    • +
    • sfdx sgd:source:delta -> sf sgd:source:delta
    • +
    • sfdx force:org:create -> sf org create sandbox | sf org create scratch
    • +
    • sfdx force:org:list -> sf org list
    • +
    • sfdx force:org:delete -> sf org delete scratch
    • +
    • sfdx config:get -> sf config get
    • +
    • sfdx config:set -> sf config set
    • +
    • sfdx auth:web:login -> sf org login web
    • +
    • sfdx auth:jwt:grant -> sf org login jwt
    • +
    • sfdx auth:sfdxurl:store -> sf org login sfdx-url
    • +
    • sfdx org:login:device -> sf org login device
    • +
    • sfdx force:data:record:get -> sf data get record
    • +
    • sfdx force:data:record:update -> sf data update record
    • +
    • sfdx force:data:soql:query -> sf data query
    • +
    • sfdx force:data:bulk:delete -> sf data delete bulk
    • +
    • sfdx alias:list -> sf alias list
    • +
    • sfdx alias:set -> sf alias set
    • +
    • sfdx force:apex:test:run -> sf apex run test
    • +
    • sfdx force:apex:execute -> sf apex run
    • +
    • sfdx force:package:create -> sf package create
    • +
    • sfdx force:package:version:create -> sf package version create
    • +
    • sfdx force:package:version:delete -> sf package version delete
    • +
    • sfdx force:package:version:list -> sf package version list
    • +
    • sfdx force:package:version:promote -> sf package version promote
    • +
    • sfdx force:package:installed:list -> sf package installed
    • +
    • sfdx force:package:install -> sf package install
    • +
    • sfdx force:user:password:generate -> sf org generate password
    • +
    • sfdx force:user:permset:assign -> sf org assign permset
    • +
    • sfdx hardis:_ -> sf hardis:_
    • +
    +
  • +
+
    +
  • New wrappers commands for SF Cli deployment commands
      +
    • sf hardis project deploy validate -> Wraps sf project deploy validate
    • +
    • sf hardis project deploy quick -> Wraps sf project deploy quick
    • +
    • sf hardis project deploy start -> Wraps sf project deploy start
    • +
    +
  • +
+

New Features / Enhancements

+
    +
  • hardis:project:deploy:smart
      +
    • New feature useSmartDeploymentTests: Improve performances by not running test classes when delta deployment contain only non impacting metadatas, and target org is not production
    • +
    • Rename command hardis:project:deploy:source:dx into hardis:project:deploy:smart (previous command alias remains, no need to update your pipelines !)
    • +
    +
  • +
  • commandsPreDeploy and commandsPostDeploy
      +
    • New option context for a command, defining when it is run and when it is not: all (default), check-deployment-only or process-deployment-only
    • +
    • New option runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)
    • +
    +
  • +
  • New commands
      +
    • hardis:project:deploy:simulate to validate the deployment of a single metadata (used by VsCode extension)
    • +
    • hardis:org:diagnose:releaseupdates to check for org Release Updates from Monitoring or locally
    • +
    • hardis:misc:purge-references to partially automate the cleaning of related dependencies when you need to delete a field, or change its type (for example from master detail to lookup)
    • +
    • hardis:project:clean:sensitive-metadatas to mask sensitive metadatas from git repo (ex: Certificate content)
    • +
    +
  • +
  • hardis:work:save and hardis:project:deploy:sources:dx: Improve runtime performances thanks to internalization of sfdx-essentials commands
  • +
  • hardis:work:new
      +
    • Allow to add labels in property availableTargetBranches, using a comma. For examples, - integration,Choose this branch if you are on the BUILD side of the project !
    • +
    • Add current default org in the choices when prompting which org to use
    • +
    +
  • +
  • hardis:project:new
      +
    • Initialize autoCleanTypes with destructivechanges, flowPositions and minimizeProfiles
    • +
    • Initialize package-no-overwrite.xml with Certificate metadata. (certificates must be uploaded manually)
    • +
    +
  • +
  • hardis:org:files:export: Improve display with spinner
  • +
  • hardis:org:purge:flow: If FlowInterview records are preventing Flow Versions to be deleted, prompt user to delete Flow Interviews before trying again to delete Flow Versions
  • +
  • hardis:project:generate:gitdelta: Add option to generate package.xml related to a single commit
  • +
  • hardis:org:data:delete: Check for property "runnableInProduction" in export.json before running deletion in production org.
  • +
  • hardis:org:diagnose:audittrail: Add new filtered actions
      +
    • Customer Portal: createdcustomersuccessuser
    • +
    +
  • +
  • Authentication: do not use alias MY_ORG anymore + do not update local user config if no values to replace.
  • +
  • When selecting an org, make sure it is still connected. If not, open browser so the user can authenticate again.
  • +
  • Update sfdx-hardis Grafana Dashboards to import in your Grafana Cloud
      +
    • SF Instance name
    • +
    • Next platform upgrade
    • +
    • Release Updates to check
    • +
    • Installed packages
    • +
    • Org licenses
    • +
    +
  • +
  • AI Deployment assistant
      +
    • Add error Change Matching Rule
    • +
    +
  • +
  • Git Providers
      +
    • On Pull Requests / Merge Requests comments, add hyperlinks to errors documentation URL
    • +
    +
  • +
+

Fixes

+
    +
  • Avoid error when removing obsolete flows (workaround using SF CLI if tooling api connection fails). Fixes #662
  • +
  • Improve Slack/Teams notifications display
  • +
  • Display explicit error message in case a password is required to install a managed package.
  • +
+

Documentation

+
    +
  • Reorganize README content
      +
    • Add link to Dreamforce 24 session
    • +
    +
  • +
  • Deployment assistant: Improve documentation by adding examples of errors, and a standalone page for each tip
  • +
  • Factorize the definition of DOC_ROOT_URL https://sfdx-hardis.cloudity.com
  • +
+

Deprecations

+
    +
  • +

    Deprecate wrapper commands matching sfdx commands that will be removed. All replaced by sf hardis deploy start

    +
      +
    • sfdx hardis:source:push
    • +
    • sfdx hardis:source:deploy
    • +
    • sfdx hardis:mdapi:retrieve
    • +
    • sfdx hardis:mdapi:deploy
    • +
    +
  • +
+
    +
  • Deprecate hardis:deploy:sources:metadata as nobody uses metadata format anymore
  • +
+

Removals

+
    +
  • Replace puppeteer by puppeteer-core: it means that if you use a command requiring puppeteer, please make sure to have a Chrome available in your environment (already integrated within the Docker image)
  • +
+
    +
  • +

    Get rid of sfdx-essentials plugin dependency by internalizing its used commands

    +
      +
    • sf hardis:packagexml:append
    • +
    • sf hardis:packagexml:remove
    • +
    • sf hardis:project:clean:filter-xml-content
    • +
    +
  • +
+
    +
  • +

    Remove npm dependencies (some of them not maintained anymore)

    +
      +
    • @adobe/node-fetch-retry
    • +
    • @amplitude/node
    • +
    • @keyv/redis
    • +
    • @oclif/command
    • +
    • @oclif/config
    • +
    • @oclif/errors
    • +
    • @salesforce/command
    • +
    • @salesforce/ts-types
    • +
    • find-package-json
    • +
    • node-fetch
    • +
    +
  • +
+
    +
  • Remove not used keyValueStores to keep only Salesforce one
  • +
+

[4.53.0] 2024-08-20

+ +

[4.52.0] 2024-08-02

+
    +
  • Minimum Node version is now 20
  • +
  • hardis:work:save : Improve performances when cleaning project files
  • +
  • Update Pipelines to add NOTIF_EMAIL_ADDRESS where it was missing
  • +
  • Remove MS_TEAMS_WEBHOOK_URL from all pipelines as MsTeamsProvider is deprecated (use EmailProvider instead)
  • +
  • Remove some useless code in EmailProvider
  • +
  • Replace glob-promise by glob package
  • +
+

[4.51.0] 2024-08-01

+
    +
  • Deprecate Microsoft Teams Web Hooks notifications +
  • +
  • Handle bug when a branch .sfdx-hardis.yml config file is empty
  • +
  • Upgrade default API version to 61
  • +
  • Additional log when generating manifest package.xml from org
  • +
  • Add error tip: Network issue (ECONNABORTED, ECONNRESET)
  • +
+

[4.50.1] 2024-07-29

+
    +
  • Fix report file name of hardis:org:monitor:limits
  • +
  • Fix crash when GitProvider has been wrongly configured, and display information message
  • +
+

[4.50.0] 2024-07-29

+
    +
  • Add message in case of deployment check passing thanks to testCoverageNotBlocking: true
  • +
  • hardis:org:diagnose:legacyapi : Fix display error declared in bug #652
  • +
  • Run legacy api detection daily with monitoring, as logs remain only 24h
  • +
+

[4.49.1] 2024-07-27

+
    +
  • Fix 4.49.0 (deployment error handler bug)
  • +
+

[4.49.0] 2024-07-27

+
    +
  • New command hardis:org:diagnose:instanceupgrade to get information about Org, its Salesforce instance and its next Platform Upgrade date. Sends notifications to Grafana if activated.
  • +
  • Refactor Monitoring checks documentation
  • +
  • hardis:project:deploy:sources:dx: After a failed Quick Deploy, use run with NoTestRun to improve perfs as we had previously succeeded to simulate the deployment
  • +
+

[4.48.1] 2024-07-26

+ +

[4.48.0] 2024-07-26

+ +

[4.47.0] 2024-07-22

+
    +
  • Update emojis in prompts to make them more visible
  • +
  • Replace sfdx force:org:open by sf org open
  • +
+

[4.46.0] 2024-07-18

+
    +
  • Allow hardis:project:deploy:source:dx notifications to work if the deployment is performed before the Pull Request is merged (see Exotic Use Case)
      +
    • Activate such mode with variable SFDX_HARDIS_DEPLOY_BEFORE_MERGE
    • +
    +
  • +
  • Add link to Conga Article
  • +
  • Add Conga article in README list of articles
  • +
+

[4.45.0] 2024-07-14

+
    +
  • New command hardis:org:files:import to import files exported using hardis:org:files:export
  • +
  • Template management for SFDMU & files import/export
  • +
  • Update JSON schema to add v60 in autoCleanTypes
  • +
+

[4.44.3] 2024-07-12

+
    +
  • Set GITLAB_API_REJECT_UNAUTHORIZED=false to avoid SSH rejections from Gitlab API
  • +
+

[4.44.2] 2024-07-09

+
    +
  • New config skipCodeCoverage, to use only in branch scoped config to not check for code coverage (Use with caution because won't work when deploying to production !)
  • +
+

[4.44.1] 2024-07-08

+
    +
  • QuickFix testlevel default value
  • +
+

[4.44.0] 2024-07-08

+
    +
  • New JSON schema properties, to use ONLY on branch scoped config and with caution !
      +
    • testLevel, to override the test level, with RunRepositoryTests for example
    • +
    • runtests, to override the list of tests to run, with ^(?!FLI|MyPrefix).* for example
    • +
    • testCoverageNotBlocking , to make code coverage not blocking on a branch
    • +
    +
  • +
  • Take in account testCoverageNotBlocking in deployment checks and PR summaries
  • +
+

[4.43.0] 2024-07-06

+
    +
  • hardis:work:save : Update prompt messages
  • +
  • Remove direct URL to target org in case of deployment failure
  • +
  • AI Deployment Assistant: Fix identification of error messages
  • +
  • Add deployment tip "Condition missing reference"
  • +
+

[4.42.0] 2024-07-02

+
    +
  • hardis:project:deploy:sources:dx : If testlevel=RunRepositoryTests, option runtests can contain a regular expression to keep only class names matching it. If not set, it will run all test classes found in the repo
  • +
  • Reduce size of README
  • +
  • Update documentation about Authentication & Security
  • +
  • Add missing variables in workflows
  • +
+

[4.41.0] 2024-06-29

+
    +
  • AI Deployment Assistant: Integrate with OpenAI ChatGPT to find solutions to deployment issues
  • +
  • Monitoring: Default 120mn timeout in Azure Workflow
  • +
  • Backup: Replace colon in package file name
  • +
  • New command hardis:project:fix:profiletabs to add / hide tabs directly in XML when such info is not retrieved by Salesforce CLI
  • +
+

[4.40.2] 2024-06-18

+
    +
  • hardis:org:diagnose:audittrail: Define new not suspect actions
      +
    • Currency
        +
      • updateddatedexchrate
      • +
      +
    • +
    • Custom App Licenses
        +
      • addeduserpackagelicense
      • +
      • granteduserpackagelicense
      • +
      +
    • +
    • Manage Users
        +
      • unfrozeuser
      • +
      +
    • +
    • Mobile Administration
        +
      • assigneduserstomobileconfig
      • +
      +
    • +
    +
  • +
  • hardis:org:monitor:all: Define relevant items as weekly, not daily
  • +
+

[4.40.1] 2024-06-17

+
    +
  • hardis:project:clean:minimizeprofiles: Allow to skip profiles refactoring using .sfdx-hardis.yml property skipMinimizeProfiles (can be useful for Experience Cloud profiles)
  • +
+

[4.40.0] 2024-06-13

+
    +
  • Deployment tips: add missingDataCategoryGroup (no DataCategoryGroup named...)
  • +
  • handle commandsPreDeploy and commandPostDeploy to run custom command before and after deployments
      +
    • If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml
    • +
    +
  • +
+

Example:

+
commandsPreDeploy:
+  - id: knowledgeUnassign
+    label: Remove KnowledgeUser right to the user who has it
+    command: sf data update record --sobject User --where "UserPermissionsKnowledgeUser='true'" --values "UserPermissionsKnowledgeUser='false'" --json
+  - id: knowledgeAssign
+    label: Assign Knowledge user to the deployment user
+    command: sf data update record --sobject User --where "Username='deploy.github@myclient.com'" --values "UserPermissionsKnowledgeUser='true'" --json
+commandsPostDeploy:
+  - id: knowledgeUnassign
+    label: Remove KnowledgeUser right to the user who has it
+    command: sf data update record --sobject User --where "UserPermissionsKnowledgeUser='true'" --values "UserPermissionsKnowledgeUser='false'" --json
+  - id: knowledgeAssign
+    label: Assign Knowledge user to the deployment user
+    command: sf data update record --sobject User --where "Username='admin.user@myclient.com'" --values "UserPermissionsKnowledgeUser='true'" --json
+
+

[4.39.0] 2024-06-13

+
    +
  • hardis:clean:references: new option v60
      +
    • Remove v61 userPermissions that do not exist in v60
    • +
    +
  • +
+

[4.38.2] 2024-06-06

+
    +
  • Fix npm packages installation for GitHub monitoring to avoid random failures
  • +
  • Add _notifKey in Grafana notifications to be able to build unique alerts
  • +
+

[4.38.1] 2024-06-04

+
    +
  • Add installed packages in monitoring backup logs
  • +
+

[4.38.0] 2024-06-03

+
    +
  • New command hardis:org:diagnose:licenses to send used licenses to monitoring logs like Grafana
  • +
  • hardis:org:diagnose:audittrail: Exclude some Add / Remove users from a Territory events from Suspect Audit Trail actions
  • +
  • hardis:org:diagnose:unusedusers: Fix metric name for ActiveUsers
  • +
+

[4.37.5] 2024-05-31

+
    +
  • hardis:org:purge:flow: Bulkify Flow deletion to improve performances
  • +
+

[4.37.4] 2024-05-28

+
    +
  • Fix pipeline and instructions for Monitoring using GitHub Actions
  • +
+

[4.37.3] 2024-05-28

+
    +
  • Revert to previous dashboards version to avoid issues with use of panel
  • +
  • Add debug capabilities for advanced cases (call with DEBUG=sfdxhardis)
  • +
+

[4.37.2] 2024-05-27

+
    +
  • Half-automate the retrieve of default Grafana Dashboards
  • +
  • Fix ticketing collection on PR with GitHub integration
  • +
  • Fix monitoring bitbucket pipeline so the git pull works
  • +
+

[4.37.1] 2024-05-26

+
    +
  • Truncate logs sent to Grafana Loki in case they are too big, to avoid they are not taken in account
      +
    • Default truncate size: 500
    • +
    +
  • +
  • Add flowPositions in .sfdx-hardis.yml JSON Schema
  • +
  • Add Grafana Cloud setup tutorial
  • +
+

[4.37.0] 2024-05-21

+
    +
  • New command hardis:project:clean:flowpositions to replace positions by 0 on AutoLayout Flows, in order to diminish conflicts
      +
    • Can be automated at each hardis:work:save if flowPositions added in .sfdx-hardis.yml autoCleanTypes property
    • +
    +
  • +
+

[4.36.0] 2024-05-19

+
    +
  • Update hardis:org:diagnose:unusedusers so it can also extract active users on a time period, thanks to option --returnactiveusers
  • +
  • Add ACTIVE_USERS in weekly monitoring jobs
  • +
  • Add JIRA variables to GitHub Workflows
  • +
+

[4.35.2] 2024-05-15

+
    +
  • Update monitoring default Gitlab, Azure & GitHub Workflows
  • +
+

[4.35.1] 2024-05-14

+
    +
  • Fix unused users notification identifier
  • +
+

[4.35.0] 2024-05-14

+
    +
  • New command sfdx hardis:org:diagnose:unusedusers to find users that don't use their license !
  • +
+

[4.34.1] 2024-05-13

+
    +
  • Notifications org identifier: replace dot by __ to avoid mess with Grafana label filters
  • +
+

[4.34.0] 2024-05-12

+
    +
  • NotifProvider
      +
    • Updates to also send metrics to Prometheus
    • +
    • NOTIFICATIONS_DISABLE is now not applicable to ApiProvider who always sends notifs
    • +
    +
  • +
+

[4.33.2] 2024-05-06

+
    +
  • hardis:org:test:apex : Always send coverageValue, coverageTarget and the list of failing classes to API logs
  • +
+

[4.33.1] 2024-05-05

+
    +
  • Api logs enhancements:
      +
    • Add severity and severityIcon in all log elements details
    • +
    • Add dateTime property (ISO format) in all API logs
    • +
    +
  • +
  • Remove deprecated way to call MsTeams notifications
  • +
  • hardis:org:monitor:limits : Fix bug when some values are not returned
  • +
+

[4.33.0] 2024-05-04

+
    +
  • New notifications provider: ApiProvider (beta), that allows to send notifications via HTTP/JSON to remote endpoints, like Grafana Loki, but also any custom one
  • +
  • New notification severity level: log, to send notifications via ApiProvider even when there is no detected issue
  • +
  • Update all existing notifications to add detailed log lines and additional log data
  • +
  • hardis:org:diagnose:audittrail: Fix lastndays not taken in account in some contexts
  • +
  • Complete refactoring of hardis:org:test:apex (same behavior but much organized code)
  • +
  • Notifications: Display success logs in blue
  • +
  • New monitoring command: sfdx hardis:org:monitor:limits to alert in case org limits are over 50% or 75% usage
  • +
  • Fix gitlab-ci-config.yml: More restrictive regex for deployment branches
  • +
+

[4.32.2] 2024-05-01

+
    +
  • Fix GitHub Actions check deploy workflow
  • +
+

[4.32.1] 2024-04-30

+
    +
  • hardis:work:new : Replace all non alphanumeric characters in new git branch name
  • +
+

[4.32.0] 2024-04-24

+ +
    +
  • Remove useless close WebSocket issue display
  • +
+

[4.31.2] 2024-04-10

+
    +
  • QuickFix Monitoring setup
  • +
+

[4.31.1] 2024-04-10

+
    +
  • Fix json output (remove other console logs that are not supposed to be here)
  • +
+

[4.31.0] 2024-04-10

+
    +
  • Add native Jenkins integration with Jenkinsfile for CI/CD Pipeline
  • +
  • Update default pipelines to add JIRA variables
  • +
  • Better handle of Jira API issues
  • +
+

[4.30.0] 2024-04-02

+
    +
  • Fix default package-no-overwrite.xml (typos on NamesCredential & RemoteSiteSetting)
  • +
  • Add links to FAQ in documentation
  • +
  • Add two new PMD rules for quality pmd-ruleset-high.xml and pmd-ruleset-medium.xml
  • +
+

[4.29.0] 2024-03-25

+
    +
  • Handle manifest/preDestructiveChanges.xml to delete items before deployments if necessary
  • +
  • Update documentation about integrations
  • +
  • Upgrade dependencies
  • +
+

[4.28.4] 2024-03-11

+
    +
  • Allow to override default scratch org duration using .sfdx-hardis.yml property scratchOrgDuration
  • +
+

[4.28.3] 2024-03-05

+
    +
  • Audit trail check: Ignore change phone number events
  • +
+

[4.28.2] 2024-02-27

+
    +
  • Fix wrong upgrade version notification
  • +
  • Update PMD bypassing rules doc
  • +
+

[4.28.1] 2024-02-26

+
    +
  • Fix issue when using email notifications with multiple recipients
  • +
+

[4.28.0] 2024-02-21

+
    +
  • Minimum Node.js version is now v18
  • +
  • New notifications channel: EmailProvider (use variable NOTIF_EMAIL_ADDRESS that can contain a comma-separated list of e-mail addresses)
  • +
  • Update existing call to notifications to add attached files when Email notif channel is active
  • +
  • Audit trail suspect actions: add the number of occurences for each suspect action found
  • +
  • Add more not suspect actions: dkimRotationPreparationSuccessful,createdReportJob,deletedReportJob,DeleteSandbox
  • +
  • Get tickets info: also check in ticket ids in branch name
  • +
  • Remove force config restDeploy=true
  • +
  • Rename Provided by sfdx-hardis into Powered by sfdx-hardis
  • +
+

[4.27.1] 2024-02-10

+
    +
  • Skip post-deployment notifications if nothing was deployed in delta mode
  • +
  • Simplify JIRA post deployment error output
  • +
+

[4.27.0] 2024-02-09

+
    +
  • Skip legacy notifications if NotifProvider has been used
  • +
  • Allow to send warning, error and critical notifications to secondary Slack or Teams channel, using variables SLACK_CHANNEL_ID_ERRORS_WARNINGS or MS_TEAMS_WEBHOOK_URL_ERRORS_WARNINGS
  • +
+

[4.26.3] 2024-02-02

+
    +
  • Add bash to sfdx-hardis docker image
  • +
+

[4.26.2] 2024-02-01

+
    +
  • Display warning message when failed to upload connected app
  • +
  • Update documentation about how to work on a dev sandbox / scratch org
  • +
+

[4.26.1] 2024-01-31

+ +

[4.26.0] 2024-01-27

+
    +
  • Detect JIRA tickets even if there is only their identifiers in commits / PR text (see Documentation)
  • +
  • Fix PR comment ticket URL when detail has not been found on server
  • +
  • Monitoring: run non-critical commands only weekly by default (on saturdays)
  • +
+

[4.25.1] 2024-01-18

+
    +
  • Fix Microsoft Teams notifications formatting
  • +
+

[4.25.0] 2024-01-15

+
    +
  • Integration with Azure Boards (Work Items) ticketing system
      +
    • Enrich MR/PR comments by adding work items references and links
    • +
    • Enrich notifications comments by adding work items references and links
    • +
    • Post a comment and a tag on Azure Work Items when they are deployed in a major org
    • +
    +
  • +
  • Enhance JIRA integration by posting labels once an issue is deployed in a major org
  • +
+

[4.24.1] 2024-01-11

+
    +
  • Improve display of Microsoft Teams notifications
  • +
+

[4.24.0] 2024-01-09

+
    +
  • Add generic ticketing provider, that can identify any ticket references using:
      +
    • GENERIC_TICKETING_PROVIDER_REGEX (Example for EasyVista: ([R|I][0-9]+-[0-9]+))
    • +
    • GENERIC_TICKETING_PROVIDER_URL_BUILDER (Example for EasyVista: https://instance.easyvista.com/index.php?ticket={REF})
    • +
    +
  • +
+

[4.23.3] 2023-12-28

+
    +
  • hardis:org:purge:flow: Ignore managed flows - Fixes #532
  • +
  • hardis:work:new prevent parenthesis in branch name - Fixes #481
  • +
+

[4.23.2] 2023-12-25

+
    +
  • Catch errors when a JIRA comment has not been posted
  • +
  • Simplify package-no-overwrite.xml management logs
  • +
+

[4.23.1] 2023-12-25

+
    +
  • Handle case when tickets have no content
  • +
+

[4.23.0] 2023-12-25

+
    +
  • Use jira-client package instead of jira.js to be compliant not only with JIRA Cloud, but also with Jira on-premise
  • +
  • Improve delta logs
  • +
+

[4.22.0] 2023-12-24

+
    +
  • Add more info in pull requests comments
      +
    • Commits summary
    • +
    • Jira tickets
    • +
    • Manual Actions
    • +
    +
  • +
  • Integration with JIRA
      +
    • Collect tickets info JIRA server
    • +
    • Post comment on tickets once they are deployed
    • +
    +
  • +
+

[4.21.6] 2023-12-22

+
    +
  • New task: Ask confirmation before updating selected sandbox
  • +
  • Deployment tips
      +
    • Visibility is not allowed for type
    • +
    +
  • +
  • Audit trail, ignore more events
      +
    • Holidays: holiday_insert
    • +
    • loginasgrantedtopartnerbt
    • +
    +
  • +
+

[4.21.5] 2023-12-14

+
    +
  • hardis:org:diagnose:audittrail
      +
    • Display user name in logs & notifications
    • +
    • Add new excluded actions: changedemail, changedsenderemail, queueMembership, enableSIQUserNonEAC
    • +
    +
  • +
+

[4.21.4] 2023-12-12

+
    +
  • Fix the output column in the metadata status report to distinguish between inactive flows and validation rules identified in the source
  • +
+

[4.21.3] 2023-12-08

+
    +
  • Add more variables in default azure-pipelines.yml monitoring
  • +
  • Fix output file name of inactive metadatas audit
  • +
+

[4.21.2] 2023-12-08

+
    +
  • Downgrade base docker image to alpine:3.18
  • +
+

[4.21.1] 2023-12-08

+
    +
  • Update Azure Pipelines workflows to add more variables (+ error message giving this list of variables)
  • +
  • Fix notifs from Azure when spaces in url
  • +
  • Fix monitoring job on Azure
  • +
  • Add link to troubleshooting page if backup fails
  • +
  • Handle notification message when there is no apex in the project
  • +
  • Do not write report log when there are no differences during monitoring backup step
  • +
  • Do not try to post PR comments if not in check deploy job
  • +
  • Check unused licenses: fix crash when no permission set group assignments
  • +
  • Fix URL to Azure Pull Requests
  • +
  • Fix display name of PR author on Azure
  • +
+

[4.21.0] 2023-12-06

+
    +
  • hardis:lint:access: Add feature in access command to verify if an object permission exist twice or more in the same permission set
  • +
  • hardis:org:monitor:backup: Allow to exclude more metadata types using env variable MONITORING_BACKUP_SKIP_METADATA_TYPES (example: `MONITORING_BACKUP_SKIP_METADATA_TYPES=CustomLabel,StaticResource,Translation`)
  • +
  • When prompt for login, Suggest custom login URL as first choice by default
  • +
  • CICD: Update default gitlab-ci-config.yml
  • +
  • Configure Org CI Auth: Do not prevent to use main or master as production branch
  • +
+

[4.20.1] 2023-12-04

+
    +
  • Handle errors while calling monitoring commands
  • +
  • Increase jsforce Bulk API Timeout (60 seconds)
  • +
  • Set default Bulk Query retries to 3 attempts
  • +
+

[4.20.0] 2023-12-04

+
    +
  • Add feature in metadatastatus command to verify if a validation rule is inactive in the source
  • +
  • hardis:lint:metadatastatus
      +
    • Check inactive validation rules
    • +
    • Add js documentation
    • +
    +
  • +
  • Monitoring: Fix crash when a package name contains a slash
  • +
+

[4.19.1] 2023-12-03

+
    +
  • Output CSV mirror XLS files reports in a xls folder for easier browsing
  • +
  • hardis:org:diagnose:unusedlicenses
      +
    • Add more Profile & Permission Set Licenses relationships
    • +
    • Handle special cases where license is not stored on the permission set, like Sales User !
    • +
    +
  • +
+

[4.19.0] 2023-12-02

+
    +
  • New command sfdx hardis:org:diagnose:unusedlicenses to detect unused Permission Set Licenses (that you pay for anyway !)
  • +
+

[4.18.3] 2023-11-29

+
    +
  • Improve test cases notification
  • +
  • Enhance monitoring documentation with more descriptions and screenshots
  • +
+

[4.18.2] 2023-11-29

+
    +
  • hardis:work:save enhancements
      +
    • Display more output during cleaning jobs
    • +
    • Keep userPermissions in Profiles when they are defined to false
    • +
    +
  • +
+

[4.18.1] 2023-11-29

+
    +
  • Improve backup notifications display
  • +
+

[4.18.0] 2023-11-29

+
    +
  • Delta deployments is no more beta but Generally available
  • +
  • Org Monitoring is no more beta but Generally available
  • +
  • Generate CSV reports also in XSLX format for easier opening
  • +
+

[4.17.1] 2023-11-28

+
    +
  • Generate CSV output for hardis:org:monitor:backup
  • +
  • Refactor git detection of created/updated/deleted files
  • +
+

[4.17.0] 2023-11-28

+
    +
  • hardis:org:backup: Monitor installed packages
  • +
  • hardis:org:diagnose:audittrail: Add more ignored events
      +
    • Email Administration: dkimRotationSuccessful
    • +
    • Manage Users: PermSetGroupAssign
    • +
    • Manage Users: PermSetGroupUnassign
    • +
    +
  • +
  • Complete factorization of notification related methods
  • +
  • Do not remove applicationVisibilities and recordTypeVisibilities from Profiles if they are defined to false (allow to hide applications)
  • +
+

[4.16.1] 2023-11-27

+
    +
  • Core: Factorize CSV generation
  • +
+

[4.16.0] 2023-11-27

+
    +
  • Allow to run commands but disable notifications, using NOTIFICATIONS_DISABLE env var or notificationsDisable .sfdx-hardis.yml property.
  • +
  • Update JSON schema to add notificationsDisable and monitoringDisable properties
  • +
+

[4.15.1] 2023-11-26

+
    +
  • Improve notifs display with hardis:lint:access
  • +
+

[4.15.0] 2023-11-24

+
    +
  • Allow to disable not monitoring checks using monitoringDisable config file property, or MONITORING_DISABLE env var
  • +
  • Add new feature to identify custom fields without description
      +
    • hardis:lint:missingattributes : New command to identify custom field without description
    • +
    +
  • +
  • Add new feature to identify custom metadata (flows) inactive in project
      +
    • hardis:lint:metadatastatus : New command to identify custom metadata (Labels and custom permissions) not used in source code
    • +
    +
  • +
  • Rework generate csv file : generateReportPath and generateCsvFile
  • +
  • Update monitoring and slack documentation
  • +
  • Fix slack, teams & Azure notifications
  • +
+

[4.14.0] 2023-11-23

+
    +
  • Add new feature to identify custom metadata (Labels and custom permissions) not used in source code
  • +
  • hardis:lint:unusedmetadata : New command to identify custom metadata (Labels and custom permissions) not used in source code
  • +
  • Add two function getNotificationButtons and getBranchMarkdown in notifUtils.ts class to factorize code
  • +
  • Video explaining how to setup sfdx-hardis monitoring
  • +
  • Improve notifications display of lists
  • +
+

[4.13.4] 2023-11-22

+
    +
  • Upgrade ms-teams-webhook library so it works again !
  • +
  • hardis:org:diagnose:audittrail: Add changedmanager to not suspect setup actions
  • +
+

[4.13.2] 2023-11-21

+
    +
  • hardis:lint:access: Do not display empty metadata types in notification.
  • +
  • hardis:work:new: Improve prompt messages when asked if you want to refresh your sandbox
  • +
+

[4.13.1] 2023-11-21

+
    +
  • hardis:lint:access
      +
    • Exclude custom settings, custom metadata and data cloud from fields access check
    • +
    +
  • +
  • hardis:org:diagnose:audittrail
      +
    • Add changedUserEmailVerifiedStatusUnverified and useremailchangesent to not suspect setup actions
    • +
    +
  • +
  • Output info in case Ms Teams notification failed to be sent
  • +
+

[4.13.0] 2023-11-19

+
    +
  • Monitoring
      +
    • Display package.xml content in logs when backup failed
    • +
    • Update default package-skip-items.xml
    • +
    • Call hardis:lint:access by default
    • +
    • Handle empty sections
    • +
    +
  • +
  • hardis:org:diagnose:audittrail enhancements:
      +
    • Add PerSetUnassign in not suspect monitored actions in Setup Audit Trail
    • +
    • Allow to append more allowed Setup Audit Trail sections & actions using .sfdx-hardis.yml property monitoringAllowedSectionsActions
    • +
    +
  • +
  • hardis:lint:access enhancements:
      +
    • Exclude required fields and MasterDetails, that can not be defined on Permission Sets
    • +
    • Output report file
    • +
    • Send slack notification
    • +
    • Add it by default in the monitoring commands
    • +
    +
  • +
  • Doc
      +
    • Update contributing infos (use sf plugins link)
    • +
    +
  • +
  • hardis:files:export : Make the command compliant with Email attachments
  • +
+

[4.12.2] 2023-11-15

+
    +
  • Add user prompts for setup audit trail monitoring in interactive mode
  • +
+

[4.12.1] 2023-11-15

+
    +
  • Allow to exclude more usernames from monitoring using .sfdx-hardis.yml property monitoringExcludeUsernames
  • +
+

[4.12.0] 2023-11-14

+
    +
  • New command sfdx hardis:org:diagnose:audittrail to detect suspect actions in major orgs
      +
    • Run by default in org monitoring
    • +
    +
  • +
  • Fix notifications bulletpoints
  • +
  • Fix Gitlab provider token collections when in monitoring mode
  • +
+

[4.11.0] 2023-11-14

+
    +
  • If QuickDeploy failed, by default do not use delta for a deployment after a merge between a minor and a major branch
  • +
  • Allow to tweak delta deployments configuration (but it's really better to use default opinionated default config !)
  • +
+

[4.10.3] 2023-11-12

+
    +
  • Allow to configure monitoring on deployment repositories (Fix #477)
  • +
  • Forbid to configure CI authentication on main or master branch
  • +
  • Do not send legacy API notifications when there are no issues (Fix #478)
  • +
  • Upgrade dependencies
  • +
+

[4.10.2] 2023-11-07

+
    +
  • If you want to force the use full deployment on a delta project Pull Request/ Merge Request, add nodelta in your latest commit title or text.
  • +
  • Display FULL / DELTA / Quick Deploy info at the bottom of the logs.
  • +
  • sfdx hardis:org:retrieve:packageconfig: Do not replace Ids when updating the .sfdx-hardis.yml list of packages using packages listed from an org
  • +
+

[4.10.1] 2023-11-06

+
    +
  • Improve delta display in logs
  • +
  • Display Quick Deploy icon in slack notifications
  • +
  • Update Azure Pipelines default pipelines for delta deployments compliance
  • +
  • Update slack integration documentation
  • +
  • Add tutorials for authentication configuration on CI/CD servers
  • +
+

[4.10.O] 2023-11-04

+ +

[4.9.2] 2023-10-31

+
    +
  • Improve GitHub monitoring Workflow
  • +
  • Enhance monitoring documentation
  • +
+

[4.9.1] 2023-10-31

+
    +
  • New deployment error tips:
      +
    • Invalid custom summary formula definition
    • +
    +
  • +
  • Add artifacts config on bitbucket-pipelines.yml
  • +
  • Add more comments in Monitoring workflows
  • +
+

[4.9.0] 2023-10-30

+
    +
  • Refactor Monitoring configuration and execution (beta)
      +
    • If you already have a monitoring v1 repository, deprecate it and create a new one with the new monitoring setup and pipelines
    • +
    • Send slack notifications
        +
      • Latest updates detected in org
      • +
      • Failing apex tests, or insufficient code coverage
      • +
      • Deprecated API calls detected
      • +
      +
    • +
    • Full setup documentation
        +
      • GitHub Actions
      • +
      • Gitlab CI
      • +
      • Azure Pipelines
      • +
      • Bitbucket Pipelines
      • +
      +
    • +
    • Totally rewritten command sfdx hardis:org:configure:monitoring
    • +
    • New command sfdx hardis:org:monitor:backup
    • +
    • New command sfdx hardis:org:monitor:all
    • +
    +
  • +
  • Simplify sfdx hardis:project:configure:auth (Configure Org CI Authentication)
  • +
  • Disable auto-update for .gitignore & .forceignore
  • +
  • Improve documentation related to pull and commit
  • +
+

[4.8.1] 2023-10-28

+
    +
  • Catch "Cannot start the OAuth redirect server on port 1717" and give instructions to user to kill the process
  • +
+

[4.8.0] 2023-10-25

+
    +
  • Allow to use Device login for Code Builder compatibility
  • +
  • New option to clear cache if an authenticated org does not appear in the choices
  • +
+

[4.7.0] 2023-10-24

+
    +
  • hardis:org:files:export: New configuration available to export files: outputFileNameFormat, with available values:
      +
    • title (default)
    • +
    • title_id
    • +
    • id_title
    • +
    • id
    • +
    +
  • +
+

[4.6.6] 2023-10-20

+
    +
  • Fix crash when converting orgCoverage to string
  • +
+

[4.6.5] 2023-10-17

+ +

[4.6.4] 2023-09-28

+
    +
  • hardis:work:save : Fix issue when there is an empty commit because of pre-commit hooks
  • +
+

[4.6.3] 2023-09-27

+ +

[4.6.2] 2023-09-26

+
    +
  • Fix return code for wrapper commands force:source:deploy, force:source:push and force:mdapi:deploy
  • +
  • Fix --skipauth not taken in account with @salesforce/cli
  • +
  • Fixed PR coverage to use float over string
  • +
+

[4.6.1] 2023-09-26

+
    +
  • Fix auth issue with force:source & force:mdapi wrapper sfdx-hardis commands
  • +
+

[4.6.0] 2023-09-20

+ +
    +
  • +

    Native BitBucket CI/CD Pipeline for PR deployment checks and deployments to major orgs after merge

    +
      +
    • PR comments are not implemented yet but BitBucket can already be used for production
    • +
    +
  • +
+
    +
  • +

    hardis:project:deploy:dx enhancements:

    +
      +
    • Added new option --testlevel RunRepositoryTests which will dynamically detect all GIT repository test classes and runs the deployment with found tests. This will speed up the validation/deployment on cases where GIT repository module contains subset of all tests found in the org
    • +
    • Added --runtests support in order to pass certain APEX test classes when --testlevel RunSpecifiedTests is used
    • +
    +
  • +
+ +

[4.5.1] 2023-09-11

+
    +
  • GitHub Integration: Fix Quick Deploy on Pull Requests
  • +
+

[4.5.0] 2023-09-11

+
    +
  • GitHub Integration: Implement automated comments & Quick Deploy on Pull Requests
  • +
+

[4.4.0] 2023-09-10

+
    +
  • Make sfdx-hardis CI/CD Pipelines natively compliant with GitHub Actions , by @legetz
  • +
  • Create sfdx project: Change defaut first major branch name to integration (it was previously develop)
  • +
  • Update default API version to 58.0
  • +
  • Fix bug when user email is input the first time
  • +
+

[4.3.2] 2023-09-08

+
    +
  • Updates new task, commit & save task documentation & screenshots
  • +
+

[4.3.1] 2023-09-07

+
    +
  • Improve message when deploying metadata to org from local sfdx-hardis
  • +
  • Improve documentation to handle merge requests and display links at the end of hardis:work:save
  • +
+

[4.3.0] 2023-09-05

+ +

[4.2.5] 2023-09-05

+ +

[4.2.4] 2023-09-05

+ +

[4.2.3] 2023-09-04

+
    +
  • Fix issues with Org monitoring when there are issues with Legacy API
  • +
+

[4.2.2] 2023-09-01

+
    +
  • Fix upgrade warning message that should not appear when there is no upgrade to perform (detected by @mamasse19)
  • +
+

[4.2.1] 2023-08-30

+
    +
  • Fix issue in sfdx commands wrapping following the use of @salesforce/cli
  • +
  • Config auth: phrases in bold when needing to relaunch the same command after org selection
  • +
+

[4.2.0] 2023-08-30

+
    +
  • Simplify UX of hardis:project:configure:auth
  • +
  • Factorize prompting of email
  • +
  • Expire sfdx-hardis connected app token after 3h
  • +
  • Update documentation to add workaround in case there is a crash when retrieving all sources when initializing a DX project from an existing org
  • +
  • Add output to explain how to not use QuickDeploy if not wanted
  • +
  • Update Quick Deploy documentation
  • +
+

[4.1.2] 2023-08-24

+
    +
  • When there is a crash in force📦installed:list , do not crash but return empty array and display an error message
  • +
+

[4.1.1] 2023-08-23

+
    +
  • Improve error message when Git Provider not available
  • +
  • Update default azure-pipelines-deployment.yml to add mandatory variables for QuickDeploy
  • +
+
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
+CI_SFDX_HARDIS_AZURE_TOKEN: $(System.AccessToken)
+SYSTEM_COLLECTIONURI: $(System.CollectionUri)
+BUILD_REPOSITORY_ID: $(Build.Repository.ID)
+
+

[4.1.0] 2023-08-22

+
    +
  • Manage QuickDeploy when available (disable by defining env var SFDX_HARDIS_QUICK_DEPLOY=false)
  • +
+

[4.0.1] 2023-08-18

+

BREAKING CHANGE: If you are not using sfdx-hardis docker images, you need to manually update your CI/CD pipelines scripts using sfdx-hardis (gitlab-ci.yml, azure-pipelines.yml...) to:

+
    +
  • replace sfdx-cli by @salesforce/cli
  • +
  • Add sf plugins install @salesforce/plugin-packaging just after npm install @salesforce/cli --global
  • +
+

Other upgrades

+
    +
  • Upgrade CI/CD scripts and sfdx-hardis docker images from sfdx-cli to @salesforce/cli (sfdx commands remain called in background), and add @salesforce/plugin-packaging by default
  • +
  • Now also release sfdx-hardis images on GitHub Packages (ghcr.io)
  • +
  • Internal CI refactorization +
  • +
+

[3.19.4] 2023-07-18

+
    +
  • Add confirmation before resetting a git branch from VsCode command "Reset selected list of items to merge" (from an original idea of @derroman)
  • +
+

[3.19.3] 2023-07-10

+
    +
  • Allow to disable red colors for force:source:deploy output using env variable SFDX_HARDIS_DEPLOY_ERR_COLORS=false
  • +
+

[3.19.2] 2023-07-06

+
    +
  • Add packaging in online doc menu
  • +
+

[3.19.1] 2023-07-05

+
    +
  • Add Hotfix management (BUILD vs RUN) in CI/CD documentation
  • +
  • Add Packaging & package version instructions in documentation
  • +
+

[3.19.0] 2023-07-03

+
    +
  • Monitoring: Do not exclude custom fields on managed objects + -ex: Remove Ns__Object__c.Ns__Field__c, but keep Ns__Object__c.Field__c
  • +
+

[3.18.1] 2023-06-13

+
    +
  • QuickFix hardis:work:save when branch has not been created on the computer
  • +
+

[3.18.0] 2023-06-07

+ +

[3.17.0] 2022-05-30

+
    +
  • New command hardis:org:generate:packagexmlfull to generate the full package.xml of a selected Salesforce org
  • +
+

[3.16.1] 2022-05-29

+
    +
  • Also remove standard fields when running hardis:project:clean:standarditems
  • +
  • New Deployment tips
      +
    • Wrong api Version of a Metadata
    • +
    • Unknown user
    • +
    +
  • +
  • Upgrade to MegaLinter v7
  • +
+

[3.16.0] 2022-05-24

+
    +
  • New ENV variables to override default wait on retrieve/deploy/test commands
      +
    • SFDX_RETRIEVE_WAIT_MINUTES
    • +
    • SFDX_DEPLOY_WAIT_MINUTES
    • +
    • SFDX_TEST_WAIT_MINUTES
    • +
    +
  • +
  • Update default .forceignore content
  • +
+

[3.15.0] 2022-05-11

+
    +
  • Allow to define property availableProjects so when user clicks on New task (hardis:work:new), he/she is asked to select a project, that will be used to build the new git branch name
  • +
  • When creating new task, store the target branch so it is not prompted again when waiting to save/publish the task.
  • +
+

[3.14.2] 2022-05-03

+
    +
  • More explicit text to ask user if he/she wants to update its selected sandbox while creating a new task
  • +
  • Do not ask to change default target branch if there are multiple available branches
  • +
+

[3.14.1] 2022-04-19

+
    +
  • Allow to override the default deployment wait time (60) using variable SFDX_DEPLOY_WAIT_MINUTES
  • +
  • Update JSON schema to add customOrgColors
  • +
+

[3.14.0] 2022-04-14

+
    +
  • Fix breaking change of sfdx-git-delta (many thanks @scolladon !)
  • +
  • Deploy tips
      +
    • Invalid report type
    • +
    • Missing report
    • +
    • Update missing email template message
    • +
    +
  • +
  • Add more space between error lines in PR/MR comments
  • +
  • Upgrade xml2js dependency
  • +
  • Update call to MegaLinter in Azure integrations
  • +
+

[3.13.1] 2022-04-12

+
    +
  • Fix missing sfdx-git-delta in Docker image
  • +
+

[3.13.0] 2022-04-06

+
    +
  • Change defaut package install mode to AdminsOnly
  • +
  • When minimizing Profiles, do not remove the personAccountDefault=true elements
  • +
  • Add new deploy tip: Error parsing file
  • +
+

[3.12.3] 2022-04-04

+
    +
  • Do not add EmailTemplate and Flows as separate items in deploymentPlan, as metadata API now can handle their deployment with the rest of the sources
  • +
  • Add new deployTip: Missing multi-currency field
  • +
  • Update label when creating a new task using an existing sandbox
  • +
+

[3.12.2] 2022-03-30

+
    +
  • New deployment error tips
      +
    • SortOrder must be in sequential order from 1. (Duplicate Rules issue)
    • +
    • Invalid field:ACCOUNT.NAME in related list:RelatedContactAccountRelationList
    • +
    +
  • +
  • Add more matchers for duplicate detector
  • +
+

[3.12.1] 2022-03-29

+
    +
  • Fix false positive error in deployment job when there is no related Pull/Merge request
  • +
+

[3.12.0] 2022-03-23

+ +

[3.11.1] 2022-03-20

+
    +
  • Better fix for root path issues (internal error)
  • +
+

[3.11.0] 2022-03-20

+
    +
  • Fix root path issues (internal error)
  • +
+

[3.10.2] 2022-03-16

+
    +
  • Fix sandbox check when calling hardis:source:push
  • +
+

[3.10.1] 2022-03-15

+
    +
  • Quick fix Gitlab integration when there is no MR associated to a deployment
  • +
+

[3.10.0] 2022-03-15

+
    +
  • Post a Gitlab Merge Request note when checking a deployment (beta)
      +
    • Deployment errors with resolution tips
    • +
    • Failing test classes
    • +
    • Code coverage
    • +
    +
  • +
  • Do not remove then restore lookup filters when source:push on a source-tracked sandbox
  • +
  • Catch and display errors when caused by internet connection issue
  • +
+

[3.9.2] 2022-03-09

+
    +
  • Update deploy tips for error Unknown user permission: SendExternalEmailAvailable
  • +
+

[3.9.1] 2022-03-08

+
    +
  • Improve logs for false positive after package installation failure
  • +
  • Remove useless and scary log after a successful login :)
  • +
  • Remove npm cache from Docker image
  • +
+

[3.9.0] 2022-03-08

+
    +
  • New task with source tracked sandbox:
      +
    • Do not allow to select a major org for dev or config
    • +
    • Open SF org if selected from the already connected list
    • +
    • Init packages only if defined in config
    • +
    • Enhance labels
    • +
    +
  • +
  • Save task: Notify that once the merge request is merged, you must create a new task that will create a new branch
  • +
  • Improve login error messages
  • +
  • Use latest version of MegaLinter
  • +
+

[3.8.0] 2022-03-03

+
    +
  • Manage deprecation of force:mdapi:legacy:deploy, replaced by force:mdapi:deploy
  • +
  • Update default packageDeployOnce.xml when creating a new project (related to Overwrite management)
  • +
  • Update CI/CD documentation
      +
    • Initialize orgs
    • +
    +
  • +
  • Update labels of prompts when creating a new sfdx-hardis project
  • +
+

[3.7.1] 2022-02-27

+ +

[3.7.0] 2022-02-27

+ +

[3.6.0] 2022-02-23

+
    +
  • Add sfdx sources to monitoring for better readability
  • +
  • Change example of email addresses for prompts
  • +
  • Update CI/CD recommendations in documentation
  • +
+

[3.5.0] 2022-02-22

+
    +
  • Update default overwrite config (packageDeployOnce.xml)
  • +
  • Setup CI: Define default Azure pipelines YML files
  • +
  • Fix notification logs for Azure Pipelines
  • +
+

[3.4.0] 2022-02-21

+ +

[3.3.2] 2022-02-17

+
    +
  • Fix default monitoring for Azure pipelines
  • +
  • Update CI documentation (Azure)
  • +
+

[3.3.1] 2022-02-16

+
    +
  • Fix check of newer package installed
  • +
+

[3.3.0] 2022-02-14

+
    +
  • Compliance of monitoring setup with Azure Pipelines
  • +
  • hardis:org:retrieve:source:metadata enhancements
      +
    • new option --includemanaged, disabled by default, to avoid having too many items to retrieve during monitoring job
    • +
    • allow to force monitoring additional tasks using env var SFDX_HARDIS_MONITORING set to "true"
    • +
    +
  • +
+

[3.2.0] 2022-02-10

+
    +
  • Fix issue when logging to a new org during command hardis:source:retrieve
  • +
  • Implement check of code coverage when calling sfdx hardis:project:deploy:sources:dx --check
      +
    • 75% minimum by default, overridable in property apexTestsMinCoverageOrgWide in .sfdx-hardis.yml, or using env var APEX_TESTS_MIN_COVERAGE_ORG_WIDE
    • +
    +
  • +
  • Add --checkcoverage option to wrapper command hardis:source:deploy
      +
    • Example: sfdx hardis:source:deploy -x manifest/package.xml --wait 60 --ignorewarnings --testlevel RunLocalTests --postdestructivechanges ./manifest/destructiveChanges.xml --targetusername nicolas.vuillamy@cloudity.com --checkonly --checkcoverage --verbose --coverageformatters json-summary
    • +
    +
  • +
+

[3.1.0] 2022-02-07

+
    +
  • Reset local sfdx tracking when reusing a sandbox for a new task
  • +
+

[3.0.0] 2022-02-07

+
    +
  • Breaking change: SFDX_HARDIS_DEPLOY_IGNORE_SPLIT_PACKAGES is now "true" by default. If you want to apply the deploymentPlan in .sfdx-hardis, you need to define variable SFDX_HARDIS_DEPLOY_IGNORE_SPLIT_PACKAGES="false"
  • +
+

[2.100.0] 2022-02-07

+
    +
  • hardis:work:new:: When creating a new task and using a source-tracked sandbox, ask user to push sources, assign permission sets and load data to initialize it.
  • +
  • Add explicit error message when scratch org creation is caused by a limit reach
  • +
  • Update default API version to 56.0
  • +
  • Improve labels when prompting to select an org
  • +
  • Update CI/CD documentation
  • +
+

[2.99.1] 2022-01-31

+
    +
  • Fix hardis:project:clean:hiddenitems when multiple files in the same folder match the same glob pattern
  • +
  • Update documentation, fix typos and dead links
  • +
+

[2.99.0] 2022-01-30

+
    +
  • Replace prompts library by inquirer, because prompts is buggy
  • +
  • Dockerfile: Workaround for https://github.com/forcedotcom/salesforcedx-apex/issues/213 (force:apex:test:run with code coverage crashing on some Gitlab runners with Invalid time value)
  • +
  • Allow to override the proposed branch names when calling hardis:work:new, using property branchPrefixChoices
  • +
  • hardis:project:clean:hiddenitems: Also clean LWC with hidden content
  • +
  • Add yarn in dockerfile
  • +
+

[2.98.1] 2022-01-23

+ +

[2.98.0] 2022-01-23

+
    +
  • Documentation: Add CI/CD user guide and release manager guide, available at https://sfdx-hardis.cloudity.com/salesforce-ci-cd-home/
  • +
  • New .sfdx-hardis.yml config property allowedOrgTypes, allowing to define the type(s) or org that can be used for implementation: (sandbox and/or scratch)
  • +
+

[2.97.3] 2022-11-30

+
    +
  • QuickFix System.debug removal
  • +
+

[2.97.2] 2022-11-30

+
    +
  • QuickFix
  • +
+

[2.97.1] 2022-11-30

+
    +
  • QuickFix hardis:lint:access
  • +
+

[2.97.0] 2022-11-30

+
    +
  • New command hardis:lint:access to analyze of items in sources are not present within profiles and/or permission sets
  • +
+

[2.96.1] 2022-11-17

+
    +
  • Fix error when assigning already existing PS
  • +
  • Update default CI config
  • +
+

[2.96.0] 2022-11-09

+
    +
  • Replace sfdx force:package:install with sfdx force:package:beta:install
  • +
  • Do not cause deployment to fail when a deploying an older managed package version
      +
    • Instead, deployment will assume the newer version meets the requirement
    • +
    +
  • +
  • hardis:scratch:create : Avoid error in case of already existing assignment of PermissionSet SfdxHardisDeferSharingRecalc
  • +
  • Update Node.js minimum version to 16.x
  • +
+

[2.95.2] 2022-10-19

+
    +
  • Replace use of sfpowerkit by default command sfdx force:source:manifest:create
  • +
  • Manage cache for listing orgs
  • +
  • Update hardis📦version:create to allow to
      +
    • install it later on an org
    • +
    • immediately delete it
    • +
    +
  • +
  • New command hardis:project:metadata:findduplicates to detect when git messed during an automated merging of conflicts
  • +
  • Factorize check of sfdx project existence
  • +
  • Fix default gitlab-ci default pipeline
  • +
  • Replace supportsDevhubUsername by requiresDevhubUsername in command classes when necessary
  • +
  • Add parameters skipauth and websocket on sfdx hardis:project:metadata:duplicate
  • +
  • Add missing parameter skipauth on sfdx hardis:package:install
  • +
+

[2.94.3] 2022-09-15

+
    +
  • Automate SSL certificate generation + force:source:deploy replaced by force:source:legacy:deploy
  • +
+

[2.94.2] 2022-09-09

+ +

[2.94.1] 2022-09-01

+
    +
  • Lock sfpowerkit dependency to 4.2.13 to avoid error caused by deprecation of sfpowerkit:org:build:manifest
  • +
+

[2.94.0] 2022-08-31

+
    +
  • Update documentation to initialize scratch org
  • +
  • Update JSON schema to add scratchOrgInitApexScripts
  • +
  • Fix execution of scripts defined in scratchOrgInitApexScripts
  • +
+

[2.93.0] 2022-08-02

+
    +
  • Fix handling of new sfdx error format so we can again identify deployment tips
  • +
  • New deployment tips:
      +
    • Cannot update a field to a Summary from something else
    • +
    +
  • +
+

[2.92.0] 2022-07-29

+
    +
  • New command hardis:org:retrieve:source:analytics to retrieve all analytics (CRM Analytics/TCRM) sources
  • +
  • New deployment tips (Wave analytics)
  • +
  • Fix writePackageXml method when there is not an existing file
  • +
+

[2.91.0] 2022-07-15

+
    +
  • Fix issue when force:source command wrappers arguments contain spaces (#269))
  • +
  • Upgrade MegaLinter to v6
  • +
  • Upgrade yarn dependencies
  • +
+

[2.90.0] 2022-06-24

+
    +
  • Events to open generated files when called from VsCode SFDX Hardis
  • +
  • New deployTips
  • +
+

[2.89.3] 2022-06-21

+
    +
  • Fix exported file extension (#266)
  • +
+

[2.89.2] 2022-06-17

+
    +
  • Build full manifest using sfpowerkit excluding ManagedContentTypeBundle because it is not managed by retrieve
  • +
+

[2.89.1] 2022-06-16

+
    +
  • Auto-update gitlab-ci.yml only if variable AUTO_UPDATE_GITLAB_CI_YML is set
  • +
+

[2.89.0] 2022-06-12

+
    +
  • hardis📦mergexml: New command to merge package.Xml files
  • +
+

[2.88.0] 2022-06-11

+
    +
  • hardis:project:clean:systemdebug: New command to comment or remove all System.debug from apex and triggers
  • +
+

[2.87.5] 2022-05-18

+
    +
  • toml2csv: Allow hardcoded values for concat
  • +
  • Refactor internal CI to use 7.148.3 as recommended version
  • +
+

[2.87.4] 2022-05-18

+
    +
  • Fix configure org CI
  • +
  • Hide auth info from console logs
  • +
  • Fix Bulk Update job not closed
  • +
+

[2.87.3] 2022-05-12

+
    +
  • Auto-update .gitlab-ci.yml if a newest version exists
  • +
+

[2.87.2] 2022-05-11

+
    +
  • Refactor report directory management
  • +
+

[2.87.1] 2022-05-11

+
    +
  • Fix monitoring default pipeline
  • +
+

[2.87.0] 2022-05-08

+
    +
  • New command hardis:project:clean:xml allowing to automate the manual cleaning in the XML files using glob pattern and xPath
  • +
  • Reorganize work:save command code + add auto mode
  • +
  • Call Save command from Retrofit command to update package.xml files and make sure sources have been cleaned
  • +
+

[2.86.1] 2022-05-06

+
    +
  • hardis:work:new : Propose to reuse current scratch org when it is not in the local list
  • +
  • hardis:work:save : Propose to push git branch on server when it is still untracked
  • +
+

[2.86.0] 2022-05-03

+
    +
  • New wrapper command: sfdx hardis:source:retrieve
  • +
  • Quickfix toml2csv
  • +
+

[2.85.2] 2022-05-02

+
    +
  • Fix toml2csv error log
  • +
  • Deployment tips
      +
    • Allow deployment with pending Apex Jobs
    • +
    • Update Can not find folder
    • +
    +
  • +
+

[2.85.1] 2022-04-27

+
    +
  • Enhance sfdx hardis:org:retrieve:sources:retrofit command + JSON schema updates
  • +
+

[2.85.0] 2022-04-27

+
    +
  • Enhance sfdx hardis:org:retrieve:sources:retrofit command
  • +
  • Ad deployment tip: Invalid field in related list
  • +
+

[2.84.0] 2022-04-27

+
    +
  • Update deployTips: improve unknown custom field message
  • +
  • New command sfdx hardis:doc:extract:permsetgroups to generate permission set groups documentation
  • +
+

[2.83.6] 2022-04-26

+
    +
  • Fix hardis:work:save who sometimes forgot to ask to push commits
  • +
+

[2.83.5] 2022-04-24

+
    +
  • Update deployment tips
  • +
+

[2.83.0] 2022-04-20

+
    +
  • New deployment tips:
      +
    • Not valid sharing model
    • +
    +
  • +
  • Improve purge flows for manual users
  • +
  • Improve badwords detector
  • +
  • Open scratch org when reusing one
  • +
  • Hide prompt result when it contains sensitive information
  • +
+

[2.82.2] 2022-04-19

+
    +
  • New deployTip: Can not change type due to existing data
  • +
  • Do not replace ListView Everything by Mine when we are just simulating deployment
  • +
+

[2.82.1] 2022-04-16

+
    +
  • QuickFix platform compatibility for sfdx hardis:org:fix:listviewmine
  • +
+

[2.82.0] 2022-04-16

+
    +
  • New command sfdx hardis:org:fix:listviewmine as a workaround to force:source:deploy not allowing ListView with scope Mine
  • +
+

[2.81.0] 2022-04-15

+
    +
  • New property autoRetrieveWhenPull to always retrieve some sources when calling hardis:source:pull (useful when sfdx tracking forgets some updates)
  • +
+

[2.80.0] 2022-04-15

+
    +
  • Simplify and document more hardis:work:new , hardis:work:pull and hardis:work:save
  • +
  • Open org in browser when fetched from scratch org pool
  • +
  • More deploymentTips
  • +
  • Add customPlugins definition in json schema
  • +
+

[2.79.0] 2022-04-10

+
    +
  • New property extends in .sfdx-hardis.yml, to allow local config file to extend from remote file
  • +
  • Add customCommands definition in json schema
  • +
+

[2.78.4] 2022-04-09

+
    +
  • Update documentation
  • +
+

[2.78.3] 2022-04-08

+
    +
  • Add a retrofit command to retrieve changes made directly in an org
  • +
+

[2.78.2] 2022-04-08

+
    +
  • Fix legacy API command display (#225)
  • +
+

[2.78.1] 2022-04-07

+
    +
  • Fix CI & remove docker image with sfdx-cli@stable as it does not exists anymore
  • +
+

[2.78.0] 2022-04-07

+
    +
  • New parameter --skipauth on all hardis commands, to allow the auth check when a default username is required (allows advanced users to improve performances)
  • +
  • Set user email when fetching a scratch org from scratch org pool
  • +
+

[2.77.2] 2022-04-07

+
    +
  • Fix bug when subtracting a package.xml from another
  • +
+

[2.77.1] 2022-04-07

+
    +
  • Fix error in packageDeployOnce.xml document (sfdx hardis:project:deploy:sources:dx)
  • +
+

[2.77.0] 2022-04-05

+
    +
  • Generate deployment tips documentation
  • +
  • hardis:org:user:activateinvalid : new --profiles argument
  • +
  • Update MsTeams WebHooks ENV variables
      +
    • MS_TEAMS_WEBHOOK_URL_CRITICAL
    • +
    • MS_TEAMS_WEBHOOK_URL_SEVERE
    • +
    • MS_TEAMS_WEBHOOK_URL_WARNING
    • +
    • MS_TEAMS_WEBHOOK_URL_INFO
    • +
    +
  • +
  • Allow to install packages during deployment check using INSTALL_PACKAGES_DURING_CHECK_DEPLOY=true env variable
  • +
  • Enhance prompt org labels
  • +
+

[2.76.2] 2022-04-04

+
    +
  • Improve activate invalid users commands (allow to select by profile(s))
  • +
+

[2.76.1] 2022-04-04

+
    +
  • Improve activate invalid users commands
  • +
+

[2.76.0] 2022-04-03

+
    +
  • New command sfdx hardis:org:user:activateinvalid to activate invalid emails in sandbox
  • +
  • Fix CI org authentication in case the default username is not the org that we want to configure
  • +
  • Bypass error with force:source:legacy:pull / push
  • +
  • hardis:work:save : Propose to manually commit files
  • +
  • Fix hardis:org:select alias & user config
  • +
  • Colorize command lines in logs
  • +
  • Enhance new task with sandbox (not fully stable yet)
  • +
  • New deployTips
      +
    • Please choose a different name
    • +
    +
  • +
+

[2.75.0] 2022-03-28

+
    +
  • Property availableTargetBranches can be defined in .sfdx-hardis.yml to list the possible target branches for merge requests
  • +
  • fix hardis:work:save to propose a git push when the current branch is ahead of origin branch
  • +
  • New deployTips
      +
    • XML item appears more than once
    • +
    +
  • +
+

[2.74.2] 2022-03-26

+
    +
  • Update legacy API detection labels
  • +
+

[2.74.1] 2022-03-25

+
    +
  • Manage crash when retrieving metadatas from CI jobs
  • +
+

[2.74.0] 2022-03-24

+
    +
  • Enhance hardis:work:save to request if the files has already been staged and committed
  • +
  • Deploy manifest and destructive change in the same sfdx force:source:deploy call thanks to new argument postdestructivechanges
  • +
  • More deployTips
  • +
  • Improve MsTeams notifications management
  • +
+

[2.73.0] 2022-03-21

+
    +
  • Improve tips about how to fix deployments directly within error messages
  • +
  • Wrapper commands to display tips in error logs
      +
    • force:source:deploy can be wrapped using hardis:source:deploy
    • +
    • force:source:push can be wrapped using hardis:source:push
    • +
    • force:mdapi:deploy can be wrapped using hardis:mdapi:deploy
    • +
    +
  • +
+

[2.72.0] 2022-03-21

+
    +
  • Include tips about how to fix deployments directly within error messages
  • +
+

[2.71.2] 2022-03-17

+
    +
  • Update JSON schema for customCommands (used by VsCode SFDX Hardis)
  • +
  • New property for scratch org pool config: maxScratchOrgsNumberToCreateOnce (max number of scratch orgs to create during one CI job)
  • +
+

[2.71.0] 2022-03-15

+
    +
  • New command hardis:org:data:delete to manage delete data workspaces of sfdmu
  • +
  • New command hardis:scratch:pool:reset to delete all scratch orgs from a scratch orgs pool (like when a new project-scratch-def is delivered)
  • +
+

[2.70.0] 2022-03-10

+
    +
  • hardis:org:apex:test : allow command to succeed when no tests are present in the project, useful for new environments initialization
  • +
+

[2.69.0] 2022-03-02

+
    +
  • Scratch org pool: add history (fetch,auth) on ActiveScratchOrg devhub record
  • +
+

[2.68.6] 2022-02-22

+
    +
  • remove DEPLOY PROGRESS noisy lines from logs
  • +
+

[2.68.5] 2022-02-18

+
    +
  • Update mkdocs
  • +
  • fix commit of files with spaces
  • +
+

[2.68.4] 2022-02-18

+
    +
  • hardis📦install
      +
    • Add -k, --installationkey CLI param and prompts user for it if not supplied
    • +
    +
  • +
+

[2.68.3] 2022-02-18

+
    +
  • Fix hardis📦version:promote --auto
  • +
+

[2.68.2] 2022-02-15

+
    +
  • Fix minimize profiles command
  • +
+

[2.68.1] 2022-02-02

+
    +
  • Allow property autoRemoveUserPermissions in .sfdx-hardis.yml to clean profiles
  • +
  • toml2csv:
      +
    • Add concatComposite option for column
    • +
    • Add recordType option for column
    • +
    +
  • +
+

[2.68.0] 2022-01-31

+
    +
  • Do not create log files in the current directory if it is empty
  • +
  • More deployTips
  • +
  • Clean MDAPI output logs from progression lines
  • +
  • Add listViewMine in cleaning references
  • +
  • toml2csv updates
  • +
+

[2.67.1] 2022-01-20

+
    +
  • Enhance documentation for hardis:scratch:pool:create command
  • +
  • Fixes and enhancements on toml2csv command
  • +
+

[2.67.0] 2022-01-18

+
    +
  • hardis:misc:toml2csv enhancements (rename and copy files)
  • +
  • fix minimizing of profiles
  • +
  • new command hardis:project:clean:listview
  • +
+

[2.66.2] 2022-01-13

+
    +
  • hardis:misc:toml2csv enhancements
  • +
+

[2.66.1] 2022-01-11

+
    +
  • minimizeProfiles: do not remove userPermissions if profile is default Admin profile
  • +
+

[2.66.0] 2022-01-07

+
    +
  • Check deployment with metadata project
  • +
+

[2.65.0] 2022-01-05

+
    +
  • Fix contribution install by upgrading dependencies
  • +
  • Use soqlQuery method everywhere
  • +
  • Set devhub alias when available
  • +
+

[2.64.1] 2021-12-29

+
    +
  • Update default apiVersion to 53.0
  • +
  • Option to not remove empty types when subtracting package.xml
  • +
+

[2.64.0] 2021-12-24

+
    +
  • New command hardis:clean:minimizeprofiles
  • +
  • New deployTip duplicate-value-platform-action-id-list
  • +
  • Apply packageDeployOnce.xml and packageDeployOnChange.xml in all contexts
  • +
  • Package.xml mixing: fix wildcard <members>*</members> management
  • +
  • List metadatas of target org: complete with what sfpowerkit commands does not return (ListView,CustomLabel)
  • +
+

[2.63.0] 2021-12-21

+
    +
  • New event message refreshPlugins (used by VsCodeSFDX Hardis)
  • +
  • Display Error message when unable to delete a temporary directory
  • +
+

[2.62.0] 2021-12-14

+
    +
  • Fix hardis:work:save crash when rebuilding deploymentPlan
  • +
  • Fix XML indentation (#51). Can also be overridden by using env variable SFDX_XML_INDENT (ex: SFDX_INDENT=' ')
  • +
+

[2.61.0] 2021-12-02

+
    +
  • Use same XML indentation than Salesforce (#51) (requires also upgrade of sfdx-essentials, using sfdx plugins:install sfdx-essentials)
  • +
+

[2.60.3] 2021-11-08

+
    +
  • Fix hardis:source:pull when there are errors
  • +
+

[2.60.2] 2021-11-06

+
    +
  • Allow to input URL to use to login
  • +
+

[2.60.1] 2021-11-05

+
    +
  • Fix hardis:scratch:pool:view when DevHub authentication is expired
  • +
+

[2.60.0] 2021-11-03

+
    +
  • Deployment failure: Tuning of error message + display of direct link to Deployment Status page in console logs
  • +
  • When not in CI, prompt for the org to use to simulate deployments
  • +
+

[2.59.0] 2021-11-03

+
    +
  • (ALPHA,not really usable yet) Allow to use sandboxes for new task (create from production org, or clone from other sandbox)
  • +
  • Fixes about scratch org initialization and JWT auth configuration
  • +
+

[2.58.3] 2021-10-23

+
    +
  • hardis:org:files:export: Fix file paths in logs
  • +
+

[2.58.2] 2021-10-18

+
    +
  • org:user:freeze : Prevent to freeze all profiles and current user profile
  • +
+

[2.58.1] 2021-10-18

+
    +
  • org:retrieve:sources:metadata : Manage locally defined remove-items-package.xml (that can handle wildcard members)
  • +
+

[2.58.0] 2021-10-16

+
    +
  • org:retrieve:sources:metadata : Run apex tests and legacy api check if we are in CI and in a repository named with monitoring
  • +
  • Teams notifications for apex tests and legacy api failure
  • +
+

[2.57.2] 2021-10-13

+
    +
  • hardis:org:files:export
      +
    • Add file extension when missing
    • +
    • replace .snote by .txt
    • +
    • replace special characters in parent folder name and file name
    • +
    +
  • +
+

[2.57.1] 2021-10-12

+
    +
  • Retry when BULK API Query returns a timeout
  • +
  • hardis:org:files:export
      +
    • Use node-fetch-retry for direct downloads (retry up to 30 seconds by default)
    • +
    • New argument --startchunknumber to start files extraction from a chunk position
    • +
    +
  • +
+

[2.57.0] 2021-10-11

+
    +
  • Make hardis:org:user:freeze and hardis:org:user:unfreeze can now handle large volume of users, using Bulk API
  • +
+

[2.56.0] 2021-10-10

+
    +
  • Update auto-generated documentation to add a commands.md + its link in the menu
  • +
+

[2.55.3] 2021-10-05

+
    +
  • When not in CI, disable auto-update of .gitignore and .forceignore files because of a prompt library issue. To enable it, define AUTO_UPDATE env variable to "true"
  • +
+

[2.55.2] 2021-10-03

+ +

[2.55.1] 2021-10-01

+
    +
  • SFDX_HARDIS_DEBUG_ENV. If set to true, display env vars at startup
  • +
+

[2.55.0] 2021-10-01

+
    +
  • Manage env var SFDX_HARDIS_DEPLOY_IGNORE_SPLIT_PACKAGES. If "true", package.xmls are not split with deploymentPlan
  • +
+

[2.54.0] 2021-09-27

+
    +
  • Allow to override force:org:create waiting time using SCRATCH_ORG_WAIT en variable (default: 15mn)
  • +
  • hardis:org:select : new parameter --scratch to allow to list only scratch orgs related to current Dev Hub
  • +
  • hardis:org:retrieve:sources:dx2 : New parameter --template to use default package.xml files (ex: wave)
  • +
  • Scratch org pool: automatically delete too old ready-to-use scratch orgs
  • +
  • Deploy Tips
      +
    • Wave deployment error
    • +
    +
  • +
+

[2.53.1] 2021-09-14

+
    +
  • Update Object deployed when configuring scratch org pool (replace Html by LongTextArea)
  • +
+

[2.53.0] 2021-09-14

+
    +
  • Additional docker images, to use when stable and latest sfdx-cli versions arr broken
      +
    • hardisgroupcom/sfdx-hardis:latest-sfdx-recommended
    • +
    • hardisgroupcom/sfdx-hardis:beta-sfdx-recommended
    • +
    • hardisgroupcom/sfdx-hardis:alpha-sfdx-recommended
    • +
    +
  • +
+

[2.52.0] 2021-09-14

+
    +
  • New command hardis:project:fix:v53flexipages to fix v53.0 broken ascending compatibility
  • +
  • New command hardis:project:audit:duplicatefiles to detect doubling files in wrong sfdx folders
  • +
+

[2.51.6] 2021-09-10

+
    +
  • Take in account parameter --ignore-whitespace of sfdx-git-delta for packageOnChange.xml
  • +
+

[2.51.5] 2021-09-10

+
    +
  • hardis:org:diagnose:legacyapi: Provide additional report with unique list of ips, hostnames (when available) , and number of calls
  • +
  • Fix hardis📦version:promote
  • +
+

[2.51.4] 2021-09-03

+
    +
  • hardis:org:diagnose:legacyapi: Allow to override default output reportfile with --outputfile argument
  • +
+

[2.51.3] 2021-09-02

+
    +
  • Improve authentication log + less cases when launching again the same command can be necessary
  • +
  • if you define forceRestDeploy: true in config, restDeploy: false won't be set automatically anymore
  • +
+

[2.51.2] 2021-08-31

+
    +
  • Quick fixes hardis:doc:plugin:generate
      +
    • Fix crash when there are no license & changelog
    • +
    +
  • +
+

[2.51.1] 2021-08-31

+
    +
  • Quick fixes hardis:doc:plugin:generate
      +
    • Handle when command.title or command.description is empty
    • +
    • Add # Commands to the README.md truncate markers
    • +
    +
  • +
  • Fix hardis:org:retrieve:sources:dx
      +
    • Empty temp directories at the beginning of the command
    • +
    • Add ForecastingType in the list of ignored metadatas for conversion to sfdx sources
    • +
    +
  • +
+

[2.51.0] 2021-08-31

+
    +
  • Update hardis:doc:plugin:generate so main README part is displayed on doc index.md
  • +
+

[2.50.0] 2021-08-30

+
    +
  • New commands to freeze users before deployment then unfreeze users after deployment
      +
    • sfdx hardis:org:user:freeze
    • +
    • sfdx hardis:org:user:unfreeze
    • +
    +
  • +
+

[2.49.1] 2021-08-30

+
    +
  • QuickFix scratch org auth during CI
  • +
+

[2.49.0] 2021-08-30

+
    +
  • Manage scratch org pools to enhance performances
      +
    • Initialize configuration with hardis:scratch:pool:configure
    • +
    • Fetch a new scratch org from the pool when requesting creation of a new scratch org
    • +
    +
  • +
+

[2.48.1] 2021-08-27

+
    +
  • QuickFix hardis:org:files:export
  • +
+

[2.48.0] 2021-08-27

+
    +
  • New command hardis:org:files:export to download all files (ContentVersion) attached to records (ex: Opportunity)
  • +
  • Generate text log file in hardis-report/commands when sfdx-hardis is not run from CI
  • +
  • hardis:org:diagnose:legacyapi : simpler logs
  • +
+

[2.47.3] 2021-08-23

+
    +
  • hardis:org:diagnose:legacyapi: Add more summary and statistics
  • +
+

[2.47.2] 2021-08-23

+
    +
  • Fix hardis:org:diagnose:legacyapi (display raw logs when CSV builder is crashing) , using papaparse instead of objects-to-csv package
  • +
+

[2.47.1] 2021-08-19

+
    +
  • Use --permissivediff to call sfdx-git-delta if the argument is available
  • +
  • Manage env vars SKIP_PACKAGE_DEPLOY_ON_CHANGE and SKIP_PACKAGE_DEPLOY_ONCE . If set to true, related packageDeployOnChange.xml and packageDeployOnce.xml are ignored
  • +
  • Define locally method to remove package.xml from another, to improve performances
  • +
+

[2.47.0] 2021-08-19

+
    +
  • New feature: use packageDeployOnChange.xml, to skip deployment of items that has not been updated since last update
  • +
  • Create docker images with sfdx-cli@stable version
      +
    • alpha-sfdx-stable
    • +
    • beta-sfdx-stable
    • +
    • latest-sfdx-stable
    • +
    +
  • +
+

[2.46.0] 2021-08-16

+
    +
  • Allow to run git delta command on local updates
  • +
  • Update labels of hardis:data commands
  • +
  • New technical command: hardis:work:ws , to call VsCode Extension refresh from CLI
  • +
+

[2.45.0] 2021-08-15

+
    +
  • Refactor hardis:org:diagnose:legacyapi with jsforce to handle more log entries
  • +
  • Do not display git branch -v in logs
  • +
+

[2.44.0] 2021-08-14

+ +

[2.43.1] 2021-07-23

+
    +
  • Update deployTips
  • +
  • Update json schema
  • +
+

[2.43.0] 2021-07-22

+
    +
  • Better split of elements during hardis:work:save
  • +
  • Display elapsed time for long running commands
  • +
+

[2.42.2] 2021-07-20

+
    +
  • Use relative path for sfdmu data import/export
  • +
+

[2.42.1] 2021-07-19

+
    +
  • Fix data import & export commands when spaces in folder names
  • +
+

[2.42.0] 2021-07-12

+
    +
  • New command sfdx hardis:project:lint
  • +
  • Update .sfdx-hardis.yml configuration JsonSchema
  • +
+

[2.41.2] 2021-07-12

+
    +
  • QuickFix case when title is not set (use first line of description)
  • +
+

[2.41.1] 2021-07-12

+
    +
  • Quickfix default mkdocs.yml
  • +
+

[2.41.0] 2021-07-12

+
    +
  • Add JSON Schema for .sfdx-hardis.yml configuration files
  • +
  • Automatic SFDX Plugin documentation generation for any SFDX Plugin
  • +
+

[2.40.0] 2021-07-08

+
    +
  • hardis:scratch:create: Initialize data using SFDMU, if defined in .sfdx-hardis.json dataPackages property with importInScratchOrgs: true
      +
    • Example
    • +
    +
  • +
+
dataPackages:
+  - dataPath: scripts/data/LightningSchedulerConfig
+    importInScratchOrgs: true
+
+
    +
  • Propose to update or not default target git branch
  • +
  • List target git branches if defined in .sfdx-hardis.json availableTargetBranches property
  • +
  • hardis:scratch:delete: Propose only scratch orgs related to currently selected Dev Hub
  • +
  • New command hardis:org:configure:data to initialize a SFDMU project, sfdx-hardis flavored
  • +
  • Display data package label & description, from SFDMU folder config.json properties sfdxHardisLabel and sfdxHardisDescription
  • +
  • hardis:org:data:import & hardis:org:data:import: Allow to select current org or another when running data import/export commands
  • +
  • Display Dev Hub username when listing orgs for selection
  • +
+

[2.31.1] 2021-07-02

+
    +
  • hardis:scratch:delete : Display instanceUrl & last usage of scratch orgs displayed before deletion
  • +
+

[2.31.0] 2021-07-02

+
    +
  • New command hardis:scratch:delete to delete scratch orgs locally referenced.
  • +
+

[2.30.1] 2021-06-30

+
    +
  • hardis:org:connect : Propose user to open org in browser if not in CI
  • +
+

[2.30.0] 2021-06-30

+
    +
  • Update hardis:org:retrieve:packageconfig so it allows to select an org, and to update sfdx-hardis configuration
  • +
+

[2.29.0] 2021-06-29

+
    +
  • New command hardis:org:retrieve:sources:dx2 to assist call to force:source:retrieve using a package.xml file
  • +
  • Improve hardis:project:generate:gitdelta by allowing to select commits from their description
  • +
  • Use magenta to display config file updates
  • +
+

[2.28.0] 2021-06-23

+
    +
  • CI: Check Docker image security with trivy
  • +
  • Avoid git error when development branch is updated
  • +
+

[2.27.1] 2021-06-21

+
    +
  • Fix CountryCode when updating scratch org user. Default FR - France, can be updated with config defaultCountry and defaultCountryCode in .sfdx-hardis.yml
  • +
+

[2.27.0] 2021-06-20

+
    +
  • Clean Lookup filters before force:source:push, then restore them and push again
  • +
  • Manage gitRootFolderPrefix config property, in case the root of git repository is at a parent level than sfdx project root
  • +
  • Allow to override separate deployments using config property separateDeploymentsConfig
  • +
  • Set git config core.quotepath to false to manage special characters in git files / folders
  • +
  • Run sfdx git delta at the root of the git repository
  • +
  • Rename DeferSharingCalc permission set into SfdxHardisDeferSharingCalc
  • +
  • New Deployment tips
  • +
  • Contributing documentation
  • +
+

[2.26.4] 2021-06-18

+
    +
  • Do not write user config when current folder is empty
  • +
+

[2.26.1] 2021-06-17

+
    +
  • Take in account testLevel from .sfdx-hardis.yml in deployments
  • +
+

[2.26.0] 2021-06-16

+
    +
  • New command hardis:project:generate:gitdelta to generate the package.xml calculated between two commits
  • +
  • New command hardis:org:connect to connect to an org without selecting it (can be used to refresh expired token)
  • +
  • Propose choice to to skip .gitignore & .forceignore files auto-update
  • +
  • Define triggerNotification on Command class to trigger MsTeams notifs
  • +
  • Update org type selection message
  • +
+

[2.25.3] 2021-06-14

+
    +
  • Fix bug when selecting an org from outside a SFDX project folder
  • +
+

[2.25.2] 2021-06-14

+
    +
  • Refresh VsCode Sfdx Hardis UI when creating / loading a SFDX Project
  • +
+

[2.25.1] 2021-06-13

+
    +
  • Check if folder is a git repo before updating git config
  • +
+

[2.25.0] 2021-06-12

+
    +
  • New parameter keepmetadatatypes for hardis:org:retrieve:sources:dx
  • +
  • Check dependencies
      +
    • Improve performances
    • +
    • Check application dependencies (git,openssl)
    • +
    +
  • +
+

[2.24.0] 2021-06-10

+
    +
  • New command hardis:org:purge:apexlog to purge all Apex Logs of selected org
  • +
+

[2.23.0] 2021-06-07

+
    +
  • Manage installation key for unlocked packages installation
  • +
  • Deployment: manage --canmodify SFDMU argument (define sfdmuCanDeploy in sfdx-hardis branch config file)
  • +
+

[2.22.0] 2021-06-03

+
    +
  • New command hardis:project:clean:orgmissingitems : Remove elements that are not existing in target org (only in ReportType for now)
  • +
  • hardis:project:clean:references : Remove cleaned items from package.xml files
  • +
  • Externalization of method to select an org (+ reorder of list of displayed orgs)
  • +
+

[2.21.0] 2021-06-02

+
    +
  • hardis:project:clean:references: Improve performances for removing files
  • +
  • hardis:scratch:create : Shorten scratch org auto-generated name
  • +
  • Authenticate to an org: Request user to set alias if not provided
  • +
  • Update default gitlab-ci.yml
  • +
  • New method promptProfiles
  • +
+

[2.20.3] 2021-05-26

+
    +
  • Set prompt UI timeout to 2h instead of 5mn
  • +
+

[2.20.2] 2021-05-25

+
    +
  • Fix call to sfdmu (add --noprompt)
  • +
+

[2.20.1] 2021-05-23

+
    +
  • Fix scratch org listing
  • +
+

[2.20.0] 2021-05-21

+
    +
  • hardis:work:save : Prompt user to pull from scratch org or not before saving
  • +
  • Do not update package.json anymore
  • +
  • hardis:scratch:create : Fix reuse scratch org prompt
  • +
+

[2.19.0] 2021-05-20

+
    +
  • Detect when auth token is expired
  • +
  • More deploy tips
  • +
  • Clean ProductRequest items
  • +
+

[2.18.0] 2021-05-18

+
    +
  • +

    New commands

    +
      +
    • hardis:org:retrieve:packageconfig: Retrieves .sfdx-hardis.yml property installedPackaged from an existing org
    • +
    • hardis:project:clean:emptyitems: Delete empty items from SFD project
    • +
    • hardis:project:clean:hiddenitems: Delete hidden items (from managed packages) from SFDX project
    • +
    +
  • +
+
    +
  • Update default values for JWT connected app creation
  • +
  • Manage --targetusername to be taken in account for all sfdx hardis commands
  • +
  • More deployment tips
  • +
  • hardis:project:clean:manageditems: New --namespace argument
  • +
  • org:retrieve:source:dx : Do not erase .gitignore, .forceignore , README.md and project-scratch-def is already existing locally
  • +
  • Remove shape temp folder to avoid a force:org:create bug
  • +
+

[2.17.3] 2021-05-18

+
    +
  • Fix .gitignore automatic update constraint
  • +
+

[2.17.2] 2021-05-10

+
    +
  • Default init scratch org using push and not deploy
  • +
  • QuickFix mergeRequest links local storage
  • +
+

[2.17.0] 2021-05-10

+
    +
  • New command hardis:project:convert:profilestopermsets to convert all profiles into permission sets
  • +
  • hardis:scratch:create : Fix permission set auto assignment when creating a scratch org (use property initPermissionSets in .sfdx-hardis.yml)
  • +
+

[2.16.1] 2021-05-09

+
    +
  • hardis:work:save : Fix storage in config file of Merge Request info
  • +
  • Update deploy tips
  • +
+

[2.16.0] 2021-05-08

+
    +
  • hardis:project:clean:manageditems : Clean SFDX project from managed classes
  • +
  • hardis:project:clean:retrievefolders: Clean/Complete SFDX project with missing folders (dashboard,email,reports)
  • +
  • hardis:project:clean:standarditems : Clean SFDX project from objects with no custom within
  • +
  • More deployment error tips
  • +
  • New parameter websocket for all commands
  • +
  • Indicating in logs when deployment is a simulation
  • +
+

[2.15.1] 2021-05-02

+
    +
  • QuickFix hardis:work:save
  • +
+

[2.15.0] 2021-04-30

+
    +
  • hardis:project:clean:references : New cleaning module dashboards removing reference to users in Dashboards sources
  • +
+

[2.14.0] 2021-04-29

+
    +
  • Manage manifest/packageDeployOnce.xml : all its items that are already present in target org will not be deployed again
  • +
+

[2.13.4] 2021-04-26

+
    +
  • New deploy tips
  • +
  • Do not update local files when calling configure commands
  • +
  • hardis:work:save : Fix branch update issue
  • +
+

[2.13.3] 2021-04-23

+
    +
  • Remove PMD rule :
      +
    • CyclomaticComplexity
    • +
    +
  • +
+

[2.13.2] 2021-04-22

+
    +
  • QuickFix hardis📦version:promote --auto
  • +
+

[2.13.0] 2021-04-21

+
    +
  • hardis:work:save
      +
    • New parameter --nogit for expert developers who want to manage git operations themselves
    • +
    • New parameter --noclean for expert developers who want to manage clean operations themselves
    • +
    +
  • +
  • Update default Mega-Linter config
  • +
+

[2.12.0] 2021-04-19

+
    +
  • New variable CI_DEPLOY_QUICK_ACTIONS_DUMMY
      +
    • set to "true" in CI variables when there are QuickActions dependent of Flows that are later in publication plan
    • +
    • then set again to "false" and the deployment will pass :)
    • +
    +
  • +
  • hardis:project:clean:references : now deletes obsolete objects and objectTranslations
  • +
  • hardis:work:save : More categories in interactive git add
  • +
  • Improve authentication check performances
  • +
  • New command hardis:config:get to return all config for project, branch or user
  • +
  • New deployment errors tips
  • +
+

[2.11.0] 2021-04-15

+
    +
  • Delete scratch org when its initialization has failed during CI
  • +
  • Clean obsolete object fields and objectTranslations
  • +
+

[2.10.4] 2021-04-15

+
    +
  • Provide password to user when creating new scratch org
  • +
  • Update CI default config to allow to not delete scratch orgs (define CI_DELETE_SCRATCH_ORG: "true" in gitlab-ci-config.yml)
  • +
  • New deploy tips: record type not found, picklist value not found
  • +
+

[2.10.3] 2021-04-14

+
    +
  • Allow advanced user to bypass auth check (set skipAuthCheck:true in config/user/***.sfdx-hardis.yml)
  • +
  • Optimize check of force:config:set restDeploy: false
  • +
  • hardis📦version:create : Store package installation password in project config + fixes
  • +
+

[2.10.2] 2021-04-14

+
    +
  • hardis:work:refresh : Make sure the user saved his work (commit) before merging another branch in current branch
  • +
+

[2.10.1] 2021-04-11

+
    +
  • hardis:org:test:apex : Fix regex to new Apex Test results stdout format
  • +
+

[2.10.0] 2021-04-11

+
    +
  • hardis:work:save : Automatic generation of split package.xml and deploymentPlan in .sfdx-hardis.yml
  • +
  • hardis:work:save : Propose to export data when saving
  • +
  • Remove duplicates from .gitignore and .forceignore
  • +
  • Add chromium in dockerfile
  • +
+

[2.9.4] 2021-04-09

+
    +
  • Fix refresh
  • +
  • Update project cleaning references
  • +
+

[2.9.3] 2021-04-08

+
    +
  • hardis:work:refresh : allow to refresh from another branch
  • +
+

[2.9.2] 2021-04-08

+
    +
  • hardis:work:save : Fix issue when trying to stage & commit ignored files after project cleaning
  • +
  • hardis:project:configure:auth Improve error message when unable to upload ConnectedApp on production environment
  • +
  • Update default Apex PMD ruleset
  • +
  • Use replace and not replaceAll for node14 compatibility
  • +
+

[2.9.1] 2021-04-07

+
    +
  • Clean git reset before save
  • +
  • Clean git stash before new task
  • +
+

[2.9.0] 2021-04-06

+
    +
  • New command hardis:project:create
  • +
  • Refactor project cleaning and allow to use external config files (destructiveChanges-like.xml or json)
  • +
  • Fixes
      +
    • hardis:work:save : Create destructiveChanges.xml if not existing
    • +
    • hardis:work:save : call forceSourcePull method to propose to update .forceignore if errors are found
    • +
    • hardis:project:configure:auth: call mdapi:deploy with RunLocalTests to manage production environments
    • +
    • authentication: auth only to devHub if --devhub sent
    • +
    • Disable spinner for restDeploy check
    • +
    +
  • +
+

[2.8.5] 2021-04-06

+
    +
  • QuickFix question icon
  • +
+

[2.8.4] 2021-04-06

+
    +
  • Allow to skip pull before save
  • +
  • New deployTip: code coverage items with 0%
  • +
  • Fix DevHub auth when credential out of date
  • +
  • Use latest sfdx-cli package
  • +
  • Init git config only if we are not in CI
  • +
+

[2.8.3] 2021-04-01

+
    +
  • Fix package creation
  • +
  • When using VsCode UI via WebSocket, display selected values in console logs
  • +
+

[2.8.2] 2021-04-01

+
    +
  • hardis:work:save : reset ongoing merge if existing
  • +
  • Fix git reset call
  • +
+

[2.8.0] 2021-03-31

+
    +
  • Define git user.name and user.email if not set
  • +
  • Define VsCode as git merge/diff tool if none is defined
  • +
  • Unstash changes (git reset) at the beginning of hardis:work:save
  • +
  • Deploy destructive changes after real deployment
  • +
  • hardis:project:clean:references now works also to remove references to content of manifest/destructiveChanges.xml
  • +
  • hardis:work:save: Clean sfdx project while saving it
  • +
  • Factorize temp directory creation
  • +
+

[2.7.2] 2021-03-30

+
    +
  • Check user is sure to want to reuse an existing scratch org
  • +
  • Fix hardis:work:refresh
  • +
+

[2.7.1] 2021-03-29

+
    +
  • Fix auto-fix of .gitignore and .forceignore
  • +
  • Propose to auto-update .force ignore when there is a pull issue
  • +
+

[2.7.0] 2021-03-29

+
    +
  • Communicate with VsCode SFDX Hardis extension via WebSocket if server is found
  • +
  • Send user input prompts to VsCode UI if WebSocket server found
  • +
  • Send refreshStatus notifications when context is updated
  • +
  • Arrange some messages for better display on UI
  • +
+

[2.6.0] 2021-03-28

+
    +
  • New command hardis:project:clean:references to clean SFDX project from data.com license references
  • +
  • hardis:scratch:create: Load sfdmu workspace scripts/data/ScratchInit if existing in , to initialize scratch org data
  • +
+

[2.5.0] 2021-03-28

+
    +
  • New command hardis:source:push
  • +
  • New command hardis:source:pull
  • +
  • Various mini-fixes
  • +
  • Move deploymentPlan.json within .sfdx-hardis.json
  • +
  • Retry management for execCommand function. ex: retry: {retryDelay: 30,retryStringConstraint: 'some string present in output', retryMaxAttempts: 5}
  • +
+

[2.4.0] 2021-03-27

+
    +
  • Add sfdmu & sfdx-git-delta in dependencies & Dockerfile
  • +
  • Import data with sfdmu
  • +
  • Manage data import steps in deploymentPlan.json
  • +
  • New command hardis:org:data:export
  • +
  • New command hardis:org:data:import
  • +
+

[2.3.0] 2021-03-26

+
    +
  • hardis:work:save: Do not git add manifest files when they have not been updated
  • +
  • Select type of org to connect: enhance label
  • +
  • Multi-Select default to 9999 items displayed
  • +
  • Display tips about deployment failures when they happen
  • +
  • Create scratch org: When DeferSharingCalc in features, suspend and resume sharing calc during force:source:push
  • +
  • Allow to define a file manifest/deploymentPlan.json to split the deployment into separate package.xml files
  • +
+

Example:

+
{
+  "packages": [
+    {
+      "label": "SharingRulesAccount",
+      "packageXmlFile": "splits/packageXmlSharingRulesAccount.xml",
+      "order": 10,
+      "waitAfter": 60
+    },
+    {
+      "label": "SharingRulesVisit__c",
+      "packageXmlFile": "splits/packageXmlSharingRulesAccountVisit__c.xml",
+      "order": 10
+    }
+  ]
+}
+
+

[2.2.1] 2021-03-23

+
    +
  • QuickFix 2.2.1
  • +
  • Use RunLocalTests when deploying ConnectedApp metadata to production org
  • +
+

[2.2.0] 2021-03-23

+
    +
  • Enhance security by encrypting SSH private key
  • +
+

[2.1.7] 2021-03-22

+
    +
  • More categories for Interactive Git Add (Aura,LWC, Tech Config)
  • +
  • Auto-update .forceignore
  • +
  • Fix hardis:org:test:apex
  • +
+

[2.1.6] 2021-03-20

+
    +
  • Fix org authentication check
  • +
+

[2.1.5] 2021-03-19

+
    +
  • Unlimited list of items displayed during interactive git add
  • +
  • Uniformize prompts to user
  • +
+

[2.1.4] 2021-03-17

+
    +
  • Deploy with --ignorewarnings
  • +
+

[2.1.3] 2021-03-17

+
    +
  • Fix hardis:retrieve:sources:dx when not in a DX project
  • +
  • Fix deloyment of Connected App in production
  • +
  • Display more options by page during interactive git add
  • +
  • Sort files to git add by group and manage preselection
  • +
+

[2.1.2] 2021-03-14

+
    +
  • Improve package installation
      +
    • Allow to install a package not listed in sfdx-hardis
    • +
    • Allow to configure automatic installation during deployments, or not
    • +
    • Allow to configure automatic installation during scratch org initialisation, or not
    • +
    +
  • +
  • Reformat strings when no spaces are allowed in a user input
  • +
+

[2.1.1] 2021-03-12

+
    +
  • Fix hardis:scratch:create when initDataRequests
  • +
+

[2.1.0] 2021-03-10

+
    +
  • New command hardis:data:tree:export
  • +
  • scratch:create: Import init data using .sfdx-hardis.yml initDataRequests property
  • +
  • scratch:create: Assign to permission set (or PS groups) using .sfdx-hardis.yml initPermissionSets property
  • +
+

[2.0.0] 2021-03-09

+
    +
  • New command hardis📦create to create Managed and Unlocked packages
  • +
  • Migrate from tslint to eslint
  • +
  • Fix dependencies hell
  • +
  • Fix hardis:org:purge:flow with new result format (#49)
  • +
+

[1.6.1] 2021-03-09

+
    +
  • Update sfdx-project.json when installing a package
  • +
  • Refresh env & scratch org if same scratch org is reused
  • +
  • Update default files for CI & monitoring projects
  • +
  • Do not deploy packages from hardis:project:deploy:sources:dx when we are in --check mode !
  • +
  • Better output display for hardis:org:test:apex
  • +
+

[1.6.0] - 2021-03-08

+
    +
  • New package commands
      +
    • hardis📦install
    • +
    • hardis📦version:create
    • +
    • hardis📦version:list
    • +
    +
  • +
+

[1.5.1] - 2021-03-07

+
    +
  • Use shared Mega-Linter configuration
  • +
+

[1.5.0] 2021-03-05

+
    +
  • New command hardis:org:select
  • +
  • New command hardis:work:resetselection
  • +
  • hardis:work:save: Upgrade package.xml and destructiveChanges.xml from git diff
  • +
  • Improve console logging of git operations
  • +
+

[1.4.1] 2021-03-03

+
    +
  • Update default gitlab-ci.yml
  • +
  • rename commands:
      +
    • hardis:work:new
    • +
    • hardis:work:refresh
    • +
    • hardis:work:save
    • +
    +
  • +
  • cosmetic enhancements
  • +
+

[1.4.0] 2021-02-28

+
    +
  • New work commands to make easier non technical users to use Hardis CI
      +
    • hardis:work:task:new
    • +
    • hardis:work:task:save
    • +
    • hardis:work:task:refresh
    • +
    +
  • +
+

[1.3.6] 2021-02-26

+
    +
  • Quick fix hardis:org:configure:monitoring + colors
  • +
+

[1.3.5] 2021-02-26

+
    +
  • Workaround when --soapdeploy argument is not available
  • +
+

[1.3.4] 2021-02-25

+
    +
  • Reuse msTeamsWebhookUrl during sfdx:org:configure:monitoring prompts
  • +
  • Allow to override CONFIG_BRANCH to get forced .sfdx.hardis.BRANCH.yml
  • +
+

[1.3.3] 2021-02-24

+
    +
  • Soap option for force:mdapi:deploy
  • +
+

[1.3.2] 2021-02-24

+
    +
  • Guide user to assign rights to Connected App in sfdx:org:configure:monitoring
  • +
+

[1.3.1] 2021-02-24

+
    +
  • Manage git clone & push for sfdx:org:configure:monitoring
  • +
  • Manage upload of connected app metadata for sfdx:org:configure:monitoring
  • +
+

[1.3.0] 2021-02-23

+
    +
  • +

    30: Remove use of sfdx-node

    +
  • +
  • New command sfdx:project:deploy:sources:metadata
  • +
  • Generate .cache folder only when necessary
  • +
  • New command sfdx:org:configure:monitoring
  • +
+

[1.2.0] 2021-02-21

+
    +
  • +

    24: Change the way of listing installed packages

    +
  • +
  • +

    26: New command sfdx hardis:project:configure:deployments to configure Connected app

    +
  • +
  • +

    27: Check in manifest folder for package.xml

    +
  • +
  • Auto-generate alpha version of plugin package and associated docker image when publishing from branch alpha
  • +
  • Manage cache storage for CI dependent jobs (cache, artifacts)
      +
    • .cache/sfdx-hardis/.sfdx
    • +
    • .sfdx
    • +
    • config/user
    • +
    +
  • +
  • Improve org authentication
  • +
  • New command hardis:org:test
      +
    • Test org coverage and fail if < 75%
    • +
    +
  • +
  • Installed package management
      +
    • Factorize method
    • +
    • Install packages during hardis:project:deploy:sources:dx
    • +
    +
  • +
  • Allow to reuse scratch org if previous creation failed. Force using --forcenew
  • +
  • Improve auto-update of local project sfdx-hardis files
  • +
  • Improve console logs
  • +
  • Allow to store DevHubSfdxClientId in user sfdx-hardis.yml ( in /user folder)
  • +
+

[1.1.3] 2021-02-17

+
    +
  • Fix cases when directory is not git
  • +
+

[1.1.0] 2021-02-17

+
    +
  • New command hardis:project:deploy:sources:dx (alpha)
  • +
  • New command hardis:project:audit:apiversion
  • +
+

[1.0.1] 2021-02-15

+
    +
  • Fix auth:login to avoid DevHub auth when not necessary
  • +
+

[1.0.0] 2021-02-15

+
    +
  • New command hardis:scratch:create
  • +
  • Advanced project initialization using --shape argument for sfdx hardis:org:retrieve:sources:dx
  • +
  • Automatic generation of .sfdx-hardis*.yml configuration files
  • +
  • Automatic update of project package.json to add sfdx-hardis utilities
  • +
+

[0.5.10] 2021-02-12

+
    +
  • Allow purges to fail without making sfdx command fail
  • +
+

[0.5.5] 2021-02-10

+
    +
  • Check if installed sfdx-hardis is the latest version, else display a message to advise the user to upgrade to latest
  • +
+

[0.5.4] 2021-02-09

+
    +
  • Fixes:
      +
    • hardis:org:purge:flow: Do not crash in case the Flow is not deletable
    • +
    +
  • +
+

[0.5.2] 2021-02-07

+
    +
  • Fixes:
      +
    • --no-prompt argument is ignored
    • +
    +
  • +
+

[0.5.1] 2021-02-04

+
    +
  • Fixes:
      +
    • Add more items to metadatas not convertible to sfdx sources
    • +
    • Issue when using --sandbox argument
    • +
    +
  • +
+

[0.5.0] 2021-02-03

+
    +
  • New command hardis:project:audit:callincallout: Audit sfdx project (or metadatas) sources to list all CallIns and CallOuts from Apex / Triggers code parsing
  • +
  • New command hardis:project:audit:remotesites: Audit sfdx project (or metadatas) sources to list all remote site settings of an org
  • +
+

[0.4.1] 2021-02-01

+
    +
  • Fix: Manage Hooks only from hardis namespace commands
  • +
+

[0.4.0] 2021-02-01

+
    +
  • Send MS Teams notifications if set environment variable MS_TEAMS_WEBHOOK_URL or msTeamsWebhookUrl in .sfdx-hardis.yml
  • +
+

[0.3.1] 2021-01-31

+
    +
  • Always regenerate full package.xml before retrieving metadatas
  • +
+

[0.3.0] 2021-01-31

+
    +
  • Build and upload nvuillam/sfdx-hardis docker image when releasing a new version
  • +
  • New command force:auth:login + manage login using JWT for CI
  • +
+

[0.2.0] 2021-01-31

+
    +
  • New command sfdx hardis:org:retrieve:sources:metadata : Retrieve all metadata from an org
  • +
+

[0.1.1] 2021-01-31

+
    +
  • New command sfdx hardis:org:retrieve:sources:dx : Create SFDX project from remote org
  • +
+

[0.0.1] 2021-01-26

+
    +
  • New command sfdx hardis:org:purge:flow : Purge Obsolete flow versions to avoid the 50 max versions limit
  • +
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 000000000..c613f8c78 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +sfdx-hardis.cloudity.com \ No newline at end of file diff --git a/assets/images/AI-Assistant.gif b/assets/images/AI-Assistant.gif new file mode 100644 index 000000000..cfda87c12 Binary files /dev/null and b/assets/images/AI-Assistant.gif differ diff --git a/assets/images/AI-deployment-assistant-console.png b/assets/images/AI-deployment-assistant-console.png new file mode 100644 index 000000000..367aa6285 Binary files /dev/null and b/assets/images/AI-deployment-assistant-console.png differ diff --git a/assets/images/AzureReporterConfigContribute.jpg b/assets/images/AzureReporterConfigContribute.jpg new file mode 100644 index 000000000..f2f389713 Binary files /dev/null and b/assets/images/AzureReporterConfigContribute.jpg differ diff --git a/assets/images/article-badwords.jpg b/assets/images/article-badwords.jpg new file mode 100644 index 000000000..ee57e9103 Binary files /dev/null and b/assets/images/article-badwords.jpg differ diff --git a/assets/images/article-cicd-salesforcedevopsnet.jpg b/assets/images/article-cicd-salesforcedevopsnet.jpg new file mode 100644 index 000000000..488e28391 Binary files /dev/null and b/assets/images/article-cicd-salesforcedevopsnet.jpg differ diff --git a/assets/images/article-conga-banner.jpg b/assets/images/article-conga-banner.jpg new file mode 100644 index 000000000..360e69d92 Binary files /dev/null and b/assets/images/article-conga-banner.jpg differ diff --git a/assets/images/article-conga.jpg b/assets/images/article-conga.jpg new file mode 100644 index 000000000..7fe513910 Binary files /dev/null and b/assets/images/article-conga.jpg differ diff --git a/assets/images/article-customize.jpg b/assets/images/article-customize.jpg new file mode 100644 index 000000000..ebf1c68d9 Binary files /dev/null and b/assets/images/article-customize.jpg differ diff --git a/assets/images/article-debugger.jpg b/assets/images/article-debugger.jpg new file mode 100644 index 000000000..c9752df9c Binary files /dev/null and b/assets/images/article-debugger.jpg differ diff --git a/assets/images/article-deployment-errors.jpg b/assets/images/article-deployment-errors.jpg new file mode 100644 index 000000000..d6eb797db Binary files /dev/null and b/assets/images/article-deployment-errors.jpg differ diff --git a/assets/images/article-deprecated-api.jpg b/assets/images/article-deprecated-api.jpg new file mode 100644 index 000000000..61da46bbd Binary files /dev/null and b/assets/images/article-deprecated-api.jpg differ diff --git a/assets/images/article-freeze.jpg b/assets/images/article-freeze.jpg new file mode 100644 index 000000000..b9ed09b52 Binary files /dev/null and b/assets/images/article-freeze.jpg differ diff --git a/assets/images/article-invalid-email.jpg b/assets/images/article-invalid-email.jpg new file mode 100644 index 000000000..771399070 Binary files /dev/null and b/assets/images/article-invalid-email.jpg differ diff --git a/assets/images/article-invalid-scope-mine.jpg b/assets/images/article-invalid-scope-mine.jpg new file mode 100644 index 000000000..3beb0188c Binary files /dev/null and b/assets/images/article-invalid-scope-mine.jpg differ diff --git a/assets/images/article-mass-download.jpg b/assets/images/article-mass-download.jpg new file mode 100644 index 000000000..50acacf17 Binary files /dev/null and b/assets/images/article-mass-download.jpg differ diff --git a/assets/images/article-questions-answers.jpg b/assets/images/article-questions-answers.jpg new file mode 100644 index 000000000..b430f6d83 Binary files /dev/null and b/assets/images/article-questions-answers.jpg differ diff --git a/assets/images/article-sfdev.jpg b/assets/images/article-sfdev.jpg new file mode 100644 index 000000000..d8df7c091 Binary files /dev/null and b/assets/images/article-sfdev.jpg differ diff --git a/assets/images/azure-pr-comment-failed-tests.jpg b/assets/images/azure-pr-comment-failed-tests.jpg new file mode 100644 index 000000000..91a88d574 Binary files /dev/null and b/assets/images/azure-pr-comment-failed-tests.jpg differ diff --git a/assets/images/azure-pr-comment-failed.jpg b/assets/images/azure-pr-comment-failed.jpg new file mode 100644 index 000000000..f8d3d9066 Binary files /dev/null and b/assets/images/azure-pr-comment-failed.jpg differ diff --git a/assets/images/azure-pr-comment.jpg b/assets/images/azure-pr-comment.jpg new file mode 100644 index 000000000..74814dda0 Binary files /dev/null and b/assets/images/azure-pr-comment.jpg differ diff --git a/assets/images/azure-pull-request-1.jpg b/assets/images/azure-pull-request-1.jpg new file mode 100644 index 000000000..1da8ee809 Binary files /dev/null and b/assets/images/azure-pull-request-1.jpg differ diff --git a/assets/images/azure-pull-request-2.jpg b/assets/images/azure-pull-request-2.jpg new file mode 100644 index 000000000..13863f475 Binary files /dev/null and b/assets/images/azure-pull-request-2.jpg differ diff --git a/assets/images/btn-clean-sources.jpg b/assets/images/btn-clean-sources.jpg new file mode 100644 index 000000000..75841c45d Binary files /dev/null and b/assets/images/btn-clean-sources.jpg differ diff --git a/assets/images/btn-configure-ci-auth.jpg b/assets/images/btn-configure-ci-auth.jpg new file mode 100644 index 000000000..5984920e3 Binary files /dev/null and b/assets/images/btn-configure-ci-auth.jpg differ diff --git a/assets/images/btn-create-project.jpg b/assets/images/btn-create-project.jpg new file mode 100644 index 000000000..4dbf82c08 Binary files /dev/null and b/assets/images/btn-create-project.jpg differ diff --git a/assets/images/btn-install-package.jpg b/assets/images/btn-install-package.jpg new file mode 100644 index 000000000..b5fb4e1ad Binary files /dev/null and b/assets/images/btn-install-package.jpg differ diff --git a/assets/images/btn-open-org.jpg b/assets/images/btn-open-org.jpg new file mode 100644 index 000000000..8df301c39 Binary files /dev/null and b/assets/images/btn-open-org.jpg differ diff --git a/assets/images/btn-package-version.jpg b/assets/images/btn-package-version.jpg new file mode 100644 index 000000000..e0644d745 Binary files /dev/null and b/assets/images/btn-package-version.jpg differ diff --git a/assets/images/btn-pull-from-org.jpg b/assets/images/btn-pull-from-org.jpg new file mode 100644 index 000000000..04eb34aee Binary files /dev/null and b/assets/images/btn-pull-from-org.jpg differ diff --git a/assets/images/btn-push-to-org.jpg b/assets/images/btn-push-to-org.jpg new file mode 100644 index 000000000..d991ee945 Binary files /dev/null and b/assets/images/btn-push-to-org.jpg differ diff --git a/assets/images/btn-reset-items.jpg b/assets/images/btn-reset-items.jpg new file mode 100644 index 000000000..8d7356894 Binary files /dev/null and b/assets/images/btn-reset-items.jpg differ diff --git a/assets/images/btn-reset-tracking.jpg b/assets/images/btn-reset-tracking.jpg new file mode 100644 index 000000000..09fc63fc9 Binary files /dev/null and b/assets/images/btn-reset-tracking.jpg differ diff --git a/assets/images/btn-retrieve-packages.jpg b/assets/images/btn-retrieve-packages.jpg new file mode 100644 index 000000000..5b0b3671d Binary files /dev/null and b/assets/images/btn-retrieve-packages.jpg differ diff --git a/assets/images/btn-save-publish-task.jpg b/assets/images/btn-save-publish-task.jpg new file mode 100644 index 000000000..ad9052742 Binary files /dev/null and b/assets/images/btn-save-publish-task.jpg differ diff --git a/assets/images/btn-select-org.jpg b/assets/images/btn-select-org.jpg new file mode 100644 index 000000000..5c4684fc6 Binary files /dev/null and b/assets/images/btn-select-org.jpg differ diff --git a/assets/images/btn-select-retrieve.jpg b/assets/images/btn-select-retrieve.jpg new file mode 100644 index 000000000..a307c47dc Binary files /dev/null and b/assets/images/btn-select-retrieve.jpg differ diff --git a/assets/images/btn-start-new-task.jpg b/assets/images/btn-start-new-task.jpg new file mode 100644 index 000000000..5810d3ae0 Binary files /dev/null and b/assets/images/btn-start-new-task.jpg differ diff --git a/assets/images/build-run-branches.png b/assets/images/build-run-branches.png new file mode 100644 index 000000000..673f883d4 Binary files /dev/null and b/assets/images/build-run-branches.png differ diff --git a/assets/images/change-sets-vs-cicd.png b/assets/images/change-sets-vs-cicd.png new file mode 100644 index 000000000..ba8cb222f Binary files /dev/null and b/assets/images/change-sets-vs-cicd.png differ diff --git a/assets/images/ci-cd-schema-build-run.jpg b/assets/images/ci-cd-schema-build-run.jpg new file mode 100644 index 000000000..be6d40ba8 Binary files /dev/null and b/assets/images/ci-cd-schema-build-run.jpg differ diff --git a/assets/images/ci-cd-schema-delta-off.jpg b/assets/images/ci-cd-schema-delta-off.jpg new file mode 100644 index 000000000..f6a211ff9 Binary files /dev/null and b/assets/images/ci-cd-schema-delta-off.jpg differ diff --git a/assets/images/ci-cd-schema-delta.jpg b/assets/images/ci-cd-schema-delta.jpg new file mode 100644 index 000000000..9931b767f Binary files /dev/null and b/assets/images/ci-cd-schema-delta.jpg differ diff --git a/assets/images/ci-cd-schema-main.jpg b/assets/images/ci-cd-schema-main.jpg new file mode 100644 index 000000000..6eb5437ca Binary files /dev/null and b/assets/images/ci-cd-schema-main.jpg differ diff --git a/assets/images/ci-cd-schema-release.jpg b/assets/images/ci-cd-schema-release.jpg new file mode 100644 index 000000000..719ae8e71 Binary files /dev/null and b/assets/images/ci-cd-schema-release.jpg differ diff --git a/assets/images/cloudity-banner-1.jpg b/assets/images/cloudity-banner-1.jpg new file mode 100644 index 000000000..a603656f2 Binary files /dev/null and b/assets/images/cloudity-banner-1.jpg differ diff --git a/assets/images/cloudity-logo.jpg b/assets/images/cloudity-logo.jpg new file mode 100644 index 000000000..cd9853f4e Binary files /dev/null and b/assets/images/cloudity-logo.jpg differ diff --git a/assets/images/cloudity-logo.svg b/assets/images/cloudity-logo.svg new file mode 100644 index 000000000..e89cb93a3 --- /dev/null +++ b/assets/images/cloudity-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/cloudity-map.jpg b/assets/images/cloudity-map.jpg new file mode 100644 index 000000000..44bb7e96a Binary files /dev/null and b/assets/images/cloudity-map.jpg differ diff --git a/assets/images/cloudity-text-logo-blk.svg b/assets/images/cloudity-text-logo-blk.svg new file mode 100644 index 000000000..70f2dbcee --- /dev/null +++ b/assets/images/cloudity-text-logo-blk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/cloudity-text-logo.svg b/assets/images/cloudity-text-logo.svg new file mode 100644 index 000000000..548b160bd --- /dev/null +++ b/assets/images/cloudity-text-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/cloudity.svg b/assets/images/cloudity.svg new file mode 100644 index 000000000..722d43136 --- /dev/null +++ b/assets/images/cloudity.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/create-new-task-1.jpg b/assets/images/create-new-task-1.jpg new file mode 100644 index 000000000..ba53ed6dc Binary files /dev/null and b/assets/images/create-new-task-1.jpg differ diff --git a/assets/images/customer_platform_hg.jpg b/assets/images/customer_platform_hg.jpg new file mode 100644 index 000000000..b3c5b86cc Binary files /dev/null and b/assets/images/customer_platform_hg.jpg differ diff --git a/assets/images/dependencies-ok.jpg b/assets/images/dependencies-ok.jpg new file mode 100644 index 000000000..b7e4fa58a Binary files /dev/null and b/assets/images/dependencies-ok.jpg differ diff --git a/assets/images/deploy-tip-example.jpg b/assets/images/deploy-tip-example.jpg new file mode 100644 index 000000000..412ae09e6 Binary files /dev/null and b/assets/images/deploy-tip-example.jpg differ diff --git a/assets/images/devops-comparison.png b/assets/images/devops-comparison.png new file mode 100644 index 000000000..cf7c9fc6e Binary files /dev/null and b/assets/images/devops-comparison.png differ diff --git a/assets/images/doc-clean-xml.jpg b/assets/images/doc-clean-xml.jpg new file mode 100644 index 000000000..609b1f26b Binary files /dev/null and b/assets/images/doc-clean-xml.jpg differ diff --git a/assets/images/dreamforce-header.png b/assets/images/dreamforce-header.png new file mode 100644 index 000000000..0838980d1 Binary files /dev/null and b/assets/images/dreamforce-header.png differ diff --git a/assets/images/engine.png b/assets/images/engine.png new file mode 100644 index 000000000..d46b653ed Binary files /dev/null and b/assets/images/engine.png differ diff --git a/assets/images/extension-demo.gif b/assets/images/extension-demo.gif new file mode 100644 index 000000000..76a4f7e96 Binary files /dev/null and b/assets/images/extension-demo.gif differ diff --git a/assets/images/extension-icon.png b/assets/images/extension-icon.png new file mode 100644 index 000000000..90bce1a43 Binary files /dev/null and b/assets/images/extension-icon.png differ diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 000000000..1cf13b9f9 Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/images/flow-visual-git-diff-2.jpg b/assets/images/flow-visual-git-diff-2.jpg new file mode 100644 index 000000000..d2ea3836c Binary files /dev/null and b/assets/images/flow-visual-git-diff-2.jpg differ diff --git a/assets/images/flow-visual-git-diff.jpg b/assets/images/flow-visual-git-diff.jpg new file mode 100644 index 000000000..452695afc Binary files /dev/null and b/assets/images/flow-visual-git-diff.jpg differ diff --git a/assets/images/git-clone-1.jpg b/assets/images/git-clone-1.jpg new file mode 100644 index 000000000..812b95c0a Binary files /dev/null and b/assets/images/git-clone-1.jpg differ diff --git a/assets/images/git-clone-2.jpg b/assets/images/git-clone-2.jpg new file mode 100644 index 000000000..2e6fb5631 Binary files /dev/null and b/assets/images/git-clone-2.jpg differ diff --git a/assets/images/git-clone-3.jpg b/assets/images/git-clone-3.jpg new file mode 100644 index 000000000..868b41da1 Binary files /dev/null and b/assets/images/git-clone-3.jpg differ diff --git a/assets/images/git-clone-4.jpg b/assets/images/git-clone-4.jpg new file mode 100644 index 000000000..1ac771b45 Binary files /dev/null and b/assets/images/git-clone-4.jpg differ diff --git a/assets/images/gitlab-mr-comment-failed-tests.jpg b/assets/images/gitlab-mr-comment-failed-tests.jpg new file mode 100644 index 000000000..3050c4287 Binary files /dev/null and b/assets/images/gitlab-mr-comment-failed-tests.jpg differ diff --git a/assets/images/gitlab-mr-comment.jpg b/assets/images/gitlab-mr-comment.jpg new file mode 100644 index 000000000..359ee3f81 Binary files /dev/null and b/assets/images/gitlab-mr-comment.jpg differ diff --git a/assets/images/grafana-config-1.jpg b/assets/images/grafana-config-1.jpg new file mode 100644 index 000000000..5a86e03e2 Binary files /dev/null and b/assets/images/grafana-config-1.jpg differ diff --git a/assets/images/grafana-config-10.jpg b/assets/images/grafana-config-10.jpg new file mode 100644 index 000000000..18c36d080 Binary files /dev/null and b/assets/images/grafana-config-10.jpg differ diff --git a/assets/images/grafana-config-11.jpg b/assets/images/grafana-config-11.jpg new file mode 100644 index 000000000..d1a1a500e Binary files /dev/null and b/assets/images/grafana-config-11.jpg differ diff --git a/assets/images/grafana-config-12.jpg b/assets/images/grafana-config-12.jpg new file mode 100644 index 000000000..b09750742 Binary files /dev/null and b/assets/images/grafana-config-12.jpg differ diff --git a/assets/images/grafana-config-13.jpg b/assets/images/grafana-config-13.jpg new file mode 100644 index 000000000..38e02f846 Binary files /dev/null and b/assets/images/grafana-config-13.jpg differ diff --git a/assets/images/grafana-config-14.jpg b/assets/images/grafana-config-14.jpg new file mode 100644 index 000000000..26a4bbf44 Binary files /dev/null and b/assets/images/grafana-config-14.jpg differ diff --git a/assets/images/grafana-config-15.jpg b/assets/images/grafana-config-15.jpg new file mode 100644 index 000000000..efaa10905 Binary files /dev/null and b/assets/images/grafana-config-15.jpg differ diff --git a/assets/images/grafana-config-16.jpg b/assets/images/grafana-config-16.jpg new file mode 100644 index 000000000..bd538df53 Binary files /dev/null and b/assets/images/grafana-config-16.jpg differ diff --git a/assets/images/grafana-config-17.jpg b/assets/images/grafana-config-17.jpg new file mode 100644 index 000000000..345a438f0 Binary files /dev/null and b/assets/images/grafana-config-17.jpg differ diff --git a/assets/images/grafana-config-18.jpg b/assets/images/grafana-config-18.jpg new file mode 100644 index 000000000..e6f453007 Binary files /dev/null and b/assets/images/grafana-config-18.jpg differ diff --git a/assets/images/grafana-config-19.jpg b/assets/images/grafana-config-19.jpg new file mode 100644 index 000000000..1ee872b36 Binary files /dev/null and b/assets/images/grafana-config-19.jpg differ diff --git a/assets/images/grafana-config-2.jpg b/assets/images/grafana-config-2.jpg new file mode 100644 index 000000000..5130c29cb Binary files /dev/null and b/assets/images/grafana-config-2.jpg differ diff --git a/assets/images/grafana-config-20.jpg b/assets/images/grafana-config-20.jpg new file mode 100644 index 000000000..02a2a8043 Binary files /dev/null and b/assets/images/grafana-config-20.jpg differ diff --git a/assets/images/grafana-config-21.jpg b/assets/images/grafana-config-21.jpg new file mode 100644 index 000000000..8bc55c15f Binary files /dev/null and b/assets/images/grafana-config-21.jpg differ diff --git a/assets/images/grafana-config-3.jpg b/assets/images/grafana-config-3.jpg new file mode 100644 index 000000000..1b317cd4d Binary files /dev/null and b/assets/images/grafana-config-3.jpg differ diff --git a/assets/images/grafana-config-4.jpg b/assets/images/grafana-config-4.jpg new file mode 100644 index 000000000..28629fdac Binary files /dev/null and b/assets/images/grafana-config-4.jpg differ diff --git a/assets/images/grafana-config-5.jpg b/assets/images/grafana-config-5.jpg new file mode 100644 index 000000000..44306e563 Binary files /dev/null and b/assets/images/grafana-config-5.jpg differ diff --git a/assets/images/grafana-config-6.jpg b/assets/images/grafana-config-6.jpg new file mode 100644 index 000000000..48e67a49d Binary files /dev/null and b/assets/images/grafana-config-6.jpg differ diff --git a/assets/images/grafana-config-7.jpg b/assets/images/grafana-config-7.jpg new file mode 100644 index 000000000..c3174b325 Binary files /dev/null and b/assets/images/grafana-config-7.jpg differ diff --git a/assets/images/grafana-config-8.jpg b/assets/images/grafana-config-8.jpg new file mode 100644 index 000000000..3ae8796e0 Binary files /dev/null and b/assets/images/grafana-config-8.jpg differ diff --git a/assets/images/grafana-config-9.jpg b/assets/images/grafana-config-9.jpg new file mode 100644 index 000000000..7816b5d32 Binary files /dev/null and b/assets/images/grafana-config-9.jpg differ diff --git a/assets/images/grafana-screenshot-1.jpg b/assets/images/grafana-screenshot-1.jpg new file mode 100644 index 000000000..ec7866955 Binary files /dev/null and b/assets/images/grafana-screenshot-1.jpg differ diff --git a/assets/images/grafana-screenshot-2.png b/assets/images/grafana-screenshot-2.png new file mode 100644 index 000000000..3e00326c7 Binary files /dev/null and b/assets/images/grafana-screenshot-2.png differ diff --git a/assets/images/grafana-screenshot.jpg b/assets/images/grafana-screenshot.jpg new file mode 100644 index 000000000..f7ce35827 Binary files /dev/null and b/assets/images/grafana-screenshot.jpg differ diff --git a/assets/images/grafana-screenshot.png b/assets/images/grafana-screenshot.png new file mode 100644 index 000000000..05c3c9acc Binary files /dev/null and b/assets/images/grafana-screenshot.png differ diff --git a/assets/images/hardis-banner.jpg b/assets/images/hardis-banner.jpg new file mode 100644 index 000000000..820fbb881 Binary files /dev/null and b/assets/images/hardis-banner.jpg differ diff --git a/assets/images/hardis-button.jpg b/assets/images/hardis-button.jpg new file mode 100644 index 000000000..a3a843c60 Binary files /dev/null and b/assets/images/hardis-button.jpg differ diff --git a/assets/images/hardis-favicon.png b/assets/images/hardis-favicon.png new file mode 100644 index 000000000..42505ceb6 Binary files /dev/null and b/assets/images/hardis-favicon.png differ diff --git a/assets/images/hardis-logo.jpg b/assets/images/hardis-logo.jpg new file mode 100644 index 000000000..6c86f6e80 Binary files /dev/null and b/assets/images/hardis-logo.jpg differ diff --git a/assets/images/hardis-logo.png b/assets/images/hardis-logo.png new file mode 100644 index 000000000..2ba9ef740 Binary files /dev/null and b/assets/images/hardis-logo.png differ diff --git a/assets/images/integrations.png b/assets/images/integrations.png new file mode 100644 index 000000000..24a10e31c Binary files /dev/null and b/assets/images/integrations.png differ diff --git a/assets/images/job-deploy-msg-error-test-class.png b/assets/images/job-deploy-msg-error-test-class.png new file mode 100644 index 000000000..39d52855e Binary files /dev/null and b/assets/images/job-deploy-msg-error-test-class.png differ diff --git a/assets/images/job-deploy-msg-error.png b/assets/images/job-deploy-msg-error.png new file mode 100644 index 000000000..e61678f96 Binary files /dev/null and b/assets/images/job-deploy-msg-error.png differ diff --git a/assets/images/job-deploy-msg-success.png b/assets/images/job-deploy-msg-success.png new file mode 100644 index 000000000..b895a9ab3 Binary files /dev/null and b/assets/images/job-deploy-msg-success.png differ diff --git a/assets/images/job-megalinter-msg-success.png b/assets/images/job-megalinter-msg-success.png new file mode 100644 index 000000000..f7ef3d6ee Binary files /dev/null and b/assets/images/job-megalinter-msg-success.png differ diff --git a/assets/images/legacy-api-result.png b/assets/images/legacy-api-result.png new file mode 100644 index 000000000..f6ed87d1b Binary files /dev/null and b/assets/images/legacy-api-result.png differ diff --git a/assets/images/mascottes.jpg b/assets/images/mascottes.jpg new file mode 100644 index 000000000..028efd249 Binary files /dev/null and b/assets/images/mascottes.jpg differ diff --git a/assets/images/merge-checks.jpg b/assets/images/merge-checks.jpg new file mode 100644 index 000000000..7ae33a4fa Binary files /dev/null and b/assets/images/merge-checks.jpg differ diff --git a/assets/images/merge-request-1.jpg b/assets/images/merge-request-1.jpg new file mode 100644 index 000000000..4cd17d68c Binary files /dev/null and b/assets/images/merge-request-1.jpg differ diff --git a/assets/images/merge-request-2.jpg b/assets/images/merge-request-2.jpg new file mode 100644 index 000000000..861e4af04 Binary files /dev/null and b/assets/images/merge-request-2.jpg differ diff --git a/assets/images/merge-request-jobs-screenshot.png b/assets/images/merge-request-jobs-screenshot.png new file mode 100644 index 000000000..bc95f474c Binary files /dev/null and b/assets/images/merge-request-jobs-screenshot.png differ diff --git a/assets/images/metadata-findduplicates.png b/assets/images/metadata-findduplicates.png new file mode 100644 index 000000000..2778e16de Binary files /dev/null and b/assets/images/metadata-findduplicates.png differ diff --git a/assets/images/monitoring-architecture.jpg b/assets/images/monitoring-architecture.jpg new file mode 100644 index 000000000..061068676 Binary files /dev/null and b/assets/images/monitoring-architecture.jpg differ diff --git a/assets/images/monitoring-screenshot.png b/assets/images/monitoring-screenshot.png new file mode 100644 index 000000000..c61bcf5d7 Binary files /dev/null and b/assets/images/monitoring-screenshot.png differ diff --git a/assets/images/msg-commit-ready.jpg b/assets/images/msg-commit-ready.jpg new file mode 100644 index 000000000..510d32718 Binary files /dev/null and b/assets/images/msg-commit-ready.jpg differ diff --git a/assets/images/msg-conflicts.png b/assets/images/msg-conflicts.png new file mode 100644 index 000000000..e353b50e6 Binary files /dev/null and b/assets/images/msg-conflicts.png differ diff --git a/assets/images/msg-upgrade-plugins.jpg b/assets/images/msg-upgrade-plugins.jpg new file mode 100644 index 000000000..b12a23f33 Binary files /dev/null and b/assets/images/msg-upgrade-plugins.jpg differ diff --git a/assets/images/multi-org-query-demo.gif b/assets/images/multi-org-query-demo.gif new file mode 100644 index 000000000..fe98fca90 Binary files /dev/null and b/assets/images/multi-org-query-demo.gif differ diff --git a/assets/images/open-vs-code-azure.jpg b/assets/images/open-vs-code-azure.jpg new file mode 100644 index 000000000..b12e57ce9 Binary files /dev/null and b/assets/images/open-vs-code-azure.jpg differ diff --git a/assets/images/open-vs-code-gitlab.jpg b/assets/images/open-vs-code-gitlab.jpg new file mode 100644 index 000000000..00ae00e94 Binary files /dev/null and b/assets/images/open-vs-code-gitlab.jpg differ diff --git a/assets/images/package-password.jpg b/assets/images/package-password.jpg new file mode 100644 index 000000000..125f8c022 Binary files /dev/null and b/assets/images/package-password.jpg differ diff --git a/assets/images/play-dreamforce-session.png b/assets/images/play-dreamforce-session.png new file mode 100644 index 000000000..2793c08d7 Binary files /dev/null and b/assets/images/play-dreamforce-session.png differ diff --git a/assets/images/play-install-tuto.png b/assets/images/play-install-tuto.png new file mode 100644 index 000000000..888da241f Binary files /dev/null and b/assets/images/play-install-tuto.png differ diff --git a/assets/images/project-documentation.gif b/assets/images/project-documentation.gif new file mode 100644 index 000000000..6f7686b60 Binary files /dev/null and b/assets/images/project-documentation.gif differ diff --git a/assets/images/protected-branches.jpg b/assets/images/protected-branches.jpg new file mode 100644 index 000000000..c82b3fe46 Binary files /dev/null and b/assets/images/protected-branches.jpg differ diff --git a/assets/images/release-manager-guide-screenshot.png b/assets/images/release-manager-guide-screenshot.png new file mode 100644 index 000000000..c4da9b673 Binary files /dev/null and b/assets/images/release-manager-guide-screenshot.png differ diff --git a/assets/images/salesforce-icon.png b/assets/images/salesforce-icon.png new file mode 100644 index 000000000..0532c30e4 Binary files /dev/null and b/assets/images/salesforce-icon.png differ diff --git a/assets/images/salesforce-logo.png b/assets/images/salesforce-logo.png new file mode 100644 index 000000000..55b0142d3 Binary files /dev/null and b/assets/images/salesforce-logo.png differ diff --git a/assets/images/sandbox-create.jpg b/assets/images/sandbox-create.jpg new file mode 100644 index 000000000..bc7cfebda Binary files /dev/null and b/assets/images/sandbox-create.jpg differ diff --git a/assets/images/screenshot-access-token-gitlab.png b/assets/images/screenshot-access-token-gitlab.png new file mode 100644 index 000000000..3eb3de3e8 Binary files /dev/null and b/assets/images/screenshot-access-token-gitlab.png differ diff --git a/assets/images/screenshot-add-variable-gitlab.png b/assets/images/screenshot-add-variable-gitlab.png new file mode 100644 index 000000000..1aa4fd360 Binary files /dev/null and b/assets/images/screenshot-add-variable-gitlab.png differ diff --git a/assets/images/screenshot-apex-errors.jpg b/assets/images/screenshot-apex-errors.jpg new file mode 100644 index 000000000..574e3717c Binary files /dev/null and b/assets/images/screenshot-apex-errors.jpg differ diff --git a/assets/images/screenshot-azure-bypass-policies.png b/assets/images/screenshot-azure-bypass-policies.png new file mode 100644 index 000000000..76bc31991 Binary files /dev/null and b/assets/images/screenshot-azure-bypass-policies.png differ diff --git a/assets/images/screenshot-azure-work-item-comment.jpg b/assets/images/screenshot-azure-work-item-comment.jpg new file mode 100644 index 000000000..4802eddef Binary files /dev/null and b/assets/images/screenshot-azure-work-item-comment.jpg differ diff --git a/assets/images/screenshot-bitbucket-success.png b/assets/images/screenshot-bitbucket-success.png new file mode 100644 index 000000000..50244b699 Binary files /dev/null and b/assets/images/screenshot-bitbucket-success.png differ diff --git a/assets/images/screenshot-bitbucket-variables.png b/assets/images/screenshot-bitbucket-variables.png new file mode 100644 index 000000000..79a027c89 Binary files /dev/null and b/assets/images/screenshot-bitbucket-variables.png differ diff --git a/assets/images/screenshot-delta-deployment.jpg b/assets/images/screenshot-delta-deployment.jpg new file mode 100644 index 000000000..e44853d69 Binary files /dev/null and b/assets/images/screenshot-delta-deployment.jpg differ diff --git a/assets/images/screenshot-deploy-to-org.png b/assets/images/screenshot-deploy-to-org.png new file mode 100644 index 000000000..29d8fe698 Binary files /dev/null and b/assets/images/screenshot-deploy-to-org.png differ diff --git a/assets/images/screenshot-download-artifacts.jpg b/assets/images/screenshot-download-artifacts.jpg new file mode 100644 index 000000000..fcb544580 Binary files /dev/null and b/assets/images/screenshot-download-artifacts.jpg differ diff --git a/assets/images/screenshot-email-config.jpg b/assets/images/screenshot-email-config.jpg new file mode 100644 index 000000000..fca67613c Binary files /dev/null and b/assets/images/screenshot-email-config.jpg differ diff --git a/assets/images/screenshot-flow-doc.jpg b/assets/images/screenshot-flow-doc.jpg new file mode 100644 index 000000000..48eb27310 Binary files /dev/null and b/assets/images/screenshot-flow-doc.jpg differ diff --git a/assets/images/screenshot-full-commit.png b/assets/images/screenshot-full-commit.png new file mode 100644 index 000000000..e6b94560e Binary files /dev/null and b/assets/images/screenshot-full-commit.png differ diff --git a/assets/images/screenshot-generic-ticketing.jpg b/assets/images/screenshot-generic-ticketing.jpg new file mode 100644 index 000000000..8cf7c9af0 Binary files /dev/null and b/assets/images/screenshot-generic-ticketing.jpg differ diff --git a/assets/images/screenshot-gha-error.jpg b/assets/images/screenshot-gha-error.jpg new file mode 100644 index 000000000..660893f88 Binary files /dev/null and b/assets/images/screenshot-gha-error.jpg differ diff --git a/assets/images/screenshot-gha-success.jpg b/assets/images/screenshot-gha-success.jpg new file mode 100644 index 000000000..30a13b755 Binary files /dev/null and b/assets/images/screenshot-gha-success.jpg differ diff --git a/assets/images/screenshot-gitlab-variables.png b/assets/images/screenshot-gitlab-variables.png new file mode 100644 index 000000000..3e1319f9e Binary files /dev/null and b/assets/images/screenshot-gitlab-variables.png differ diff --git a/assets/images/screenshot-html-doc.jpg b/assets/images/screenshot-html-doc.jpg new file mode 100644 index 000000000..309fe050a Binary files /dev/null and b/assets/images/screenshot-html-doc.jpg differ diff --git a/assets/images/screenshot-jira-comment.jpg b/assets/images/screenshot-jira-comment.jpg new file mode 100644 index 000000000..a5496a0f2 Binary files /dev/null and b/assets/images/screenshot-jira-comment.jpg differ diff --git a/assets/images/screenshot-jira-gitlab.jpg b/assets/images/screenshot-jira-gitlab.jpg new file mode 100644 index 000000000..aa8dbd2ea Binary files /dev/null and b/assets/images/screenshot-jira-gitlab.jpg differ diff --git a/assets/images/screenshot-jira-slack.jpg b/assets/images/screenshot-jira-slack.jpg new file mode 100644 index 000000000..09c9a9670 Binary files /dev/null and b/assets/images/screenshot-jira-slack.jpg differ diff --git a/assets/images/screenshot-monitoring-apexcoverage-grafana.jpg b/assets/images/screenshot-monitoring-apexcoverage-grafana.jpg new file mode 100644 index 000000000..457aabd74 Binary files /dev/null and b/assets/images/screenshot-monitoring-apexcoverage-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-apextests-grafana.jpg b/assets/images/screenshot-monitoring-apextests-grafana.jpg new file mode 100644 index 000000000..f18539548 Binary files /dev/null and b/assets/images/screenshot-monitoring-apextests-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-apextests.jpg b/assets/images/screenshot-monitoring-apextests.jpg new file mode 100644 index 000000000..cbd856e87 Binary files /dev/null and b/assets/images/screenshot-monitoring-apextests.jpg differ diff --git a/assets/images/screenshot-monitoring-audittrail-grafana.jpg b/assets/images/screenshot-monitoring-audittrail-grafana.jpg new file mode 100644 index 000000000..997a9719d Binary files /dev/null and b/assets/images/screenshot-monitoring-audittrail-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-audittrail.jpg b/assets/images/screenshot-monitoring-audittrail.jpg new file mode 100644 index 000000000..f58af4350 Binary files /dev/null and b/assets/images/screenshot-monitoring-audittrail.jpg differ diff --git a/assets/images/screenshot-monitoring-azure-pipeline.png b/assets/images/screenshot-monitoring-azure-pipeline.png new file mode 100644 index 000000000..daef6ca55 Binary files /dev/null and b/assets/images/screenshot-monitoring-azure-pipeline.png differ diff --git a/assets/images/screenshot-monitoring-azure-variable.png b/assets/images/screenshot-monitoring-azure-variable.png new file mode 100644 index 000000000..56fce12b3 Binary files /dev/null and b/assets/images/screenshot-monitoring-azure-variable.png differ diff --git a/assets/images/screenshot-monitoring-backup-grafana.jpg b/assets/images/screenshot-monitoring-backup-grafana.jpg new file mode 100644 index 000000000..461744039 Binary files /dev/null and b/assets/images/screenshot-monitoring-backup-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-backup.jpg b/assets/images/screenshot-monitoring-backup.jpg new file mode 100644 index 000000000..9301e75ce Binary files /dev/null and b/assets/images/screenshot-monitoring-backup.jpg differ diff --git a/assets/images/screenshot-monitoring-backup2.jpg b/assets/images/screenshot-monitoring-backup2.jpg new file mode 100644 index 000000000..af83e2e71 Binary files /dev/null and b/assets/images/screenshot-monitoring-backup2.jpg differ diff --git a/assets/images/screenshot-monitoring-git.jpg b/assets/images/screenshot-monitoring-git.jpg new file mode 100644 index 000000000..ebc48e41c Binary files /dev/null and b/assets/images/screenshot-monitoring-git.jpg differ diff --git a/assets/images/screenshot-monitoring-github-variable-add.png.jpg b/assets/images/screenshot-monitoring-github-variable-add.png.jpg new file mode 100644 index 000000000..05f7b6692 Binary files /dev/null and b/assets/images/screenshot-monitoring-github-variable-add.png.jpg differ diff --git a/assets/images/screenshot-monitoring-github-variable.png.jpg b/assets/images/screenshot-monitoring-github-variable.png.jpg new file mode 100644 index 000000000..b10979240 Binary files /dev/null and b/assets/images/screenshot-monitoring-github-variable.png.jpg differ diff --git a/assets/images/screenshot-monitoring-inactive-metadata-grafana.jpg b/assets/images/screenshot-monitoring-inactive-metadata-grafana.jpg new file mode 100644 index 000000000..01c98e3fb Binary files /dev/null and b/assets/images/screenshot-monitoring-inactive-metadata-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-inactive-metadata.jpg b/assets/images/screenshot-monitoring-inactive-metadata.jpg new file mode 100644 index 000000000..4be6dbe50 Binary files /dev/null and b/assets/images/screenshot-monitoring-inactive-metadata.jpg differ diff --git a/assets/images/screenshot-monitoring-inactive-users-grafana.jpg b/assets/images/screenshot-monitoring-inactive-users-grafana.jpg new file mode 100644 index 000000000..75b2a4324 Binary files /dev/null and b/assets/images/screenshot-monitoring-inactive-users-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-inactive-users.jpg b/assets/images/screenshot-monitoring-inactive-users.jpg new file mode 100644 index 000000000..8ca5c501c Binary files /dev/null and b/assets/images/screenshot-monitoring-inactive-users.jpg differ diff --git a/assets/images/screenshot-monitoring-jenkins-variable.png b/assets/images/screenshot-monitoring-jenkins-variable.png new file mode 100644 index 000000000..50d863b37 Binary files /dev/null and b/assets/images/screenshot-monitoring-jenkins-variable.png differ diff --git a/assets/images/screenshot-monitoring-jobs.jpg b/assets/images/screenshot-monitoring-jobs.jpg new file mode 100644 index 000000000..b25b0017a Binary files /dev/null and b/assets/images/screenshot-monitoring-jobs.jpg differ diff --git a/assets/images/screenshot-monitoring-legacyapi-grafana.jpg b/assets/images/screenshot-monitoring-legacyapi-grafana.jpg new file mode 100644 index 000000000..daecae0bf Binary files /dev/null and b/assets/images/screenshot-monitoring-legacyapi-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-legacyapi.jpg b/assets/images/screenshot-monitoring-legacyapi.jpg new file mode 100644 index 000000000..c7d0b86b6 Binary files /dev/null and b/assets/images/screenshot-monitoring-legacyapi.jpg differ diff --git a/assets/images/screenshot-monitoring-limits-grafana.jpg b/assets/images/screenshot-monitoring-limits-grafana.jpg new file mode 100644 index 000000000..e7321d547 Binary files /dev/null and b/assets/images/screenshot-monitoring-limits-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-limits-slack.jpg b/assets/images/screenshot-monitoring-limits-slack.jpg new file mode 100644 index 000000000..5001b5fdf Binary files /dev/null and b/assets/images/screenshot-monitoring-limits-slack.jpg differ diff --git a/assets/images/screenshot-monitoring-lintaccess-grafana.jpg b/assets/images/screenshot-monitoring-lintaccess-grafana.jpg new file mode 100644 index 000000000..e8320dc0a Binary files /dev/null and b/assets/images/screenshot-monitoring-lintaccess-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-lintaccess.jpg b/assets/images/screenshot-monitoring-lintaccess.jpg new file mode 100644 index 000000000..c2744d5e7 Binary files /dev/null and b/assets/images/screenshot-monitoring-lintaccess.jpg differ diff --git a/assets/images/screenshot-monitoring-megalinter.jpg b/assets/images/screenshot-monitoring-megalinter.jpg new file mode 100644 index 000000000..c697ae048 Binary files /dev/null and b/assets/images/screenshot-monitoring-megalinter.jpg differ diff --git a/assets/images/screenshot-monitoring-missing-attributes-grafana.jpg b/assets/images/screenshot-monitoring-missing-attributes-grafana.jpg new file mode 100644 index 000000000..6a063ad93 Binary files /dev/null and b/assets/images/screenshot-monitoring-missing-attributes-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-missing-attributes.jpg b/assets/images/screenshot-monitoring-missing-attributes.jpg new file mode 100644 index 000000000..fad4f0441 Binary files /dev/null and b/assets/images/screenshot-monitoring-missing-attributes.jpg differ diff --git a/assets/images/screenshot-monitoring-schedule-bitbucket.png b/assets/images/screenshot-monitoring-schedule-bitbucket.png new file mode 100644 index 000000000..3941bc4ae Binary files /dev/null and b/assets/images/screenshot-monitoring-schedule-bitbucket.png differ diff --git a/assets/images/screenshot-monitoring-schedule-gitlab.png b/assets/images/screenshot-monitoring-schedule-gitlab.png new file mode 100644 index 000000000..c0c3cfafe Binary files /dev/null and b/assets/images/screenshot-monitoring-schedule-gitlab.png differ diff --git a/assets/images/screenshot-monitoring-unused-apex-grafana.jpg b/assets/images/screenshot-monitoring-unused-apex-grafana.jpg new file mode 100644 index 000000000..edc5a23c1 Binary files /dev/null and b/assets/images/screenshot-monitoring-unused-apex-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-unused-apex.jpg b/assets/images/screenshot-monitoring-unused-apex.jpg new file mode 100644 index 000000000..8d730e9b1 Binary files /dev/null and b/assets/images/screenshot-monitoring-unused-apex.jpg differ diff --git a/assets/images/screenshot-monitoring-unused-licenses-grafana.jpg b/assets/images/screenshot-monitoring-unused-licenses-grafana.jpg new file mode 100644 index 000000000..2e9bd6fb7 Binary files /dev/null and b/assets/images/screenshot-monitoring-unused-licenses-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-unused-licenses.jpg b/assets/images/screenshot-monitoring-unused-licenses.jpg new file mode 100644 index 000000000..ab4844b60 Binary files /dev/null and b/assets/images/screenshot-monitoring-unused-licenses.jpg differ diff --git a/assets/images/screenshot-monitoring-unused-metadatas-grafana.jpg b/assets/images/screenshot-monitoring-unused-metadatas-grafana.jpg new file mode 100644 index 000000000..6e9acc899 Binary files /dev/null and b/assets/images/screenshot-monitoring-unused-metadatas-grafana.jpg differ diff --git a/assets/images/screenshot-monitoring-unused-metadatas.jpg b/assets/images/screenshot-monitoring-unused-metadatas.jpg new file mode 100644 index 000000000..498409e13 Binary files /dev/null and b/assets/images/screenshot-monitoring-unused-metadatas.jpg differ diff --git a/assets/images/screenshot-notif-email.jpg b/assets/images/screenshot-notif-email.jpg new file mode 100644 index 000000000..b61253d74 Binary files /dev/null and b/assets/images/screenshot-notif-email.jpg differ diff --git a/assets/images/screenshot-org-browser.png b/assets/images/screenshot-org-browser.png new file mode 100644 index 000000000..aea9c8ee4 Binary files /dev/null and b/assets/images/screenshot-org-browser.png differ diff --git a/assets/images/screenshot-partial-commit-2.png b/assets/images/screenshot-partial-commit-2.png new file mode 100644 index 000000000..b831d3983 Binary files /dev/null and b/assets/images/screenshot-partial-commit-2.png differ diff --git a/assets/images/screenshot-partial-commit.png b/assets/images/screenshot-partial-commit.png new file mode 100644 index 000000000..ba0252be7 Binary files /dev/null and b/assets/images/screenshot-partial-commit.png differ diff --git a/assets/images/screenshot-project-doc-2.jpg b/assets/images/screenshot-project-doc-2.jpg new file mode 100644 index 000000000..02230219b Binary files /dev/null and b/assets/images/screenshot-project-doc-2.jpg differ diff --git a/assets/images/screenshot-project-doc.jpg b/assets/images/screenshot-project-doc.jpg new file mode 100644 index 000000000..1c81a53c9 Binary files /dev/null and b/assets/images/screenshot-project-doc.jpg differ diff --git a/assets/images/screenshot-right-click-retrieve.png b/assets/images/screenshot-right-click-retrieve.png new file mode 100644 index 000000000..897a05665 Binary files /dev/null and b/assets/images/screenshot-right-click-retrieve.png differ diff --git a/assets/images/screenshot-slack-monitoring.jpg b/assets/images/screenshot-slack-monitoring.jpg new file mode 100644 index 000000000..f19472169 Binary files /dev/null and b/assets/images/screenshot-slack-monitoring.jpg differ diff --git a/assets/images/screenshot-slack.png b/assets/images/screenshot-slack.png new file mode 100644 index 000000000..1888a8375 Binary files /dev/null and b/assets/images/screenshot-slack.png differ diff --git a/assets/images/screenshot-teams-email-1.jpg b/assets/images/screenshot-teams-email-1.jpg new file mode 100644 index 000000000..04b06fc79 Binary files /dev/null and b/assets/images/screenshot-teams-email-1.jpg differ diff --git a/assets/images/screenshot-teams-email-2.jpg b/assets/images/screenshot-teams-email-2.jpg new file mode 100644 index 000000000..1e9e60c5d Binary files /dev/null and b/assets/images/screenshot-teams-email-2.jpg differ diff --git a/assets/images/screenshot-upgrades-available.png b/assets/images/screenshot-upgrades-available.png new file mode 100644 index 000000000..8da9d3780 Binary files /dev/null and b/assets/images/screenshot-upgrades-available.png differ diff --git a/assets/images/select-package.jpg b/assets/images/select-package.jpg new file mode 100644 index 000000000..7d8b7b21f Binary files /dev/null and b/assets/images/select-package.jpg differ diff --git a/assets/images/setup-guide-screenshot.png b/assets/images/setup-guide-screenshot.png new file mode 100644 index 000000000..1c6c1164c Binary files /dev/null and b/assets/images/setup-guide-screenshot.png differ diff --git a/assets/images/sfdx-hardis-banner.png b/assets/images/sfdx-hardis-banner.png new file mode 100644 index 000000000..a76394b16 Binary files /dev/null and b/assets/images/sfdx-hardis-banner.png differ diff --git a/assets/images/sfdx-hardis-doc-home.png b/assets/images/sfdx-hardis-doc-home.png new file mode 100644 index 000000000..8f572b0af Binary files /dev/null and b/assets/images/sfdx-hardis-doc-home.png differ diff --git a/assets/images/sfdx-hardis-extension-icon.jpg b/assets/images/sfdx-hardis-extension-icon.jpg new file mode 100644 index 000000000..826cda808 Binary files /dev/null and b/assets/images/sfdx-hardis-extension-icon.jpg differ diff --git a/assets/images/sfdx-hardis-slack.png b/assets/images/sfdx-hardis-slack.png new file mode 100644 index 000000000..68c344f93 Binary files /dev/null and b/assets/images/sfdx-hardis-slack.png differ diff --git a/assets/images/special-thanks-1.png b/assets/images/special-thanks-1.png new file mode 100644 index 000000000..8df0534b3 Binary files /dev/null and b/assets/images/special-thanks-1.png differ diff --git a/assets/images/special-thanks-2.png b/assets/images/special-thanks-2.png new file mode 100644 index 000000000..8056e1837 Binary files /dev/null and b/assets/images/special-thanks-2.png differ diff --git a/assets/images/user-guide-screenshot.png b/assets/images/user-guide-screenshot.png new file mode 100644 index 000000000..e4a7e5369 Binary files /dev/null and b/assets/images/user-guide-screenshot.png differ diff --git a/assets/images/vscode-sfdx-hardis-extension.png b/assets/images/vscode-sfdx-hardis-extension.png new file mode 100644 index 000000000..5d3e3de49 Binary files /dev/null and b/assets/images/vscode-sfdx-hardis-extension.png differ diff --git a/assets/javascripts/bundle.88dd0f4e.min.js b/assets/javascripts/bundle.88dd0f4e.min.js new file mode 100644 index 000000000..fb8f31090 --- /dev/null +++ b/assets/javascripts/bundle.88dd0f4e.min.js @@ -0,0 +1,16 @@ +"use strict";(()=>{var Wi=Object.create;var gr=Object.defineProperty;var Di=Object.getOwnPropertyDescriptor;var Vi=Object.getOwnPropertyNames,Vt=Object.getOwnPropertySymbols,Ni=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,ao=Object.prototype.propertyIsEnumerable;var io=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,$=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&io(e,r,t[r]);if(Vt)for(var r of Vt(t))ao.call(t,r)&&io(e,r,t[r]);return e};var so=(e,t)=>{var r={};for(var o in e)yr.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(e!=null&&Vt)for(var o of Vt(e))t.indexOf(o)<0&&ao.call(e,o)&&(r[o]=e[o]);return r};var xr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var zi=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Vi(t))!yr.call(e,n)&&n!==r&&gr(e,n,{get:()=>t[n],enumerable:!(o=Di(t,n))||o.enumerable});return e};var Mt=(e,t,r)=>(r=e!=null?Wi(Ni(e)):{},zi(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var co=(e,t,r)=>new Promise((o,n)=>{var i=p=>{try{s(r.next(p))}catch(c){n(c)}},a=p=>{try{s(r.throw(p))}catch(c){n(c)}},s=p=>p.done?o(p.value):Promise.resolve(p.value).then(i,a);s((r=r.apply(e,t)).next())});var lo=xr((Er,po)=>{(function(e,t){typeof Er=="object"&&typeof po!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(Er,function(){"use strict";function e(r){var o=!0,n=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(k){return!!(k&&k!==document&&k.nodeName!=="HTML"&&k.nodeName!=="BODY"&&"classList"in k&&"contains"in k.classList)}function p(k){var ft=k.type,qe=k.tagName;return!!(qe==="INPUT"&&a[ft]&&!k.readOnly||qe==="TEXTAREA"&&!k.readOnly||k.isContentEditable)}function c(k){k.classList.contains("focus-visible")||(k.classList.add("focus-visible"),k.setAttribute("data-focus-visible-added",""))}function l(k){k.hasAttribute("data-focus-visible-added")&&(k.classList.remove("focus-visible"),k.removeAttribute("data-focus-visible-added"))}function f(k){k.metaKey||k.altKey||k.ctrlKey||(s(r.activeElement)&&c(r.activeElement),o=!0)}function u(k){o=!1}function d(k){s(k.target)&&(o||p(k.target))&&c(k.target)}function y(k){s(k.target)&&(k.target.classList.contains("focus-visible")||k.target.hasAttribute("data-focus-visible-added"))&&(n=!0,window.clearTimeout(i),i=window.setTimeout(function(){n=!1},100),l(k.target))}function L(k){document.visibilityState==="hidden"&&(n&&(o=!0),X())}function X(){document.addEventListener("mousemove",J),document.addEventListener("mousedown",J),document.addEventListener("mouseup",J),document.addEventListener("pointermove",J),document.addEventListener("pointerdown",J),document.addEventListener("pointerup",J),document.addEventListener("touchmove",J),document.addEventListener("touchstart",J),document.addEventListener("touchend",J)}function te(){document.removeEventListener("mousemove",J),document.removeEventListener("mousedown",J),document.removeEventListener("mouseup",J),document.removeEventListener("pointermove",J),document.removeEventListener("pointerdown",J),document.removeEventListener("pointerup",J),document.removeEventListener("touchmove",J),document.removeEventListener("touchstart",J),document.removeEventListener("touchend",J)}function J(k){k.target.nodeName&&k.target.nodeName.toLowerCase()==="html"||(o=!1,te())}document.addEventListener("keydown",f,!0),document.addEventListener("mousedown",u,!0),document.addEventListener("pointerdown",u,!0),document.addEventListener("touchstart",u,!0),document.addEventListener("visibilitychange",L,!0),X(),r.addEventListener("focus",d,!0),r.addEventListener("blur",y,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var qr=xr((hy,On)=>{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var $a=/["'&<>]/;On.exports=Pa;function Pa(e){var t=""+e,r=$a.exec(t);if(!r)return t;var o,n="",i=0,a=0;for(i=r.index;i{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof It=="object"&&typeof Yr=="object"?Yr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof It=="object"?It.ClipboardJS=r():t.ClipboardJS=r()})(It,function(){return function(){var e={686:function(o,n,i){"use strict";i.d(n,{default:function(){return Ui}});var a=i(279),s=i.n(a),p=i(370),c=i.n(p),l=i(817),f=i.n(l);function u(V){try{return document.execCommand(V)}catch(A){return!1}}var d=function(A){var M=f()(A);return u("cut"),M},y=d;function L(V){var A=document.documentElement.getAttribute("dir")==="rtl",M=document.createElement("textarea");M.style.fontSize="12pt",M.style.border="0",M.style.padding="0",M.style.margin="0",M.style.position="absolute",M.style[A?"right":"left"]="-9999px";var F=window.pageYOffset||document.documentElement.scrollTop;return M.style.top="".concat(F,"px"),M.setAttribute("readonly",""),M.value=V,M}var X=function(A,M){var F=L(A);M.container.appendChild(F);var D=f()(F);return u("copy"),F.remove(),D},te=function(A){var M=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},F="";return typeof A=="string"?F=X(A,M):A instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(A==null?void 0:A.type)?F=X(A.value,M):(F=f()(A),u("copy")),F},J=te;function k(V){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?k=function(M){return typeof M}:k=function(M){return M&&typeof Symbol=="function"&&M.constructor===Symbol&&M!==Symbol.prototype?"symbol":typeof M},k(V)}var ft=function(){var A=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},M=A.action,F=M===void 0?"copy":M,D=A.container,Y=A.target,$e=A.text;if(F!=="copy"&&F!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(Y!==void 0)if(Y&&k(Y)==="object"&&Y.nodeType===1){if(F==="copy"&&Y.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(F==="cut"&&(Y.hasAttribute("readonly")||Y.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if($e)return J($e,{container:D});if(Y)return F==="cut"?y(Y):J(Y,{container:D})},qe=ft;function Fe(V){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Fe=function(M){return typeof M}:Fe=function(M){return M&&typeof Symbol=="function"&&M.constructor===Symbol&&M!==Symbol.prototype?"symbol":typeof M},Fe(V)}function ki(V,A){if(!(V instanceof A))throw new TypeError("Cannot call a class as a function")}function no(V,A){for(var M=0;M0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof D.action=="function"?D.action:this.defaultAction,this.target=typeof D.target=="function"?D.target:this.defaultTarget,this.text=typeof D.text=="function"?D.text:this.defaultText,this.container=Fe(D.container)==="object"?D.container:document.body}},{key:"listenClick",value:function(D){var Y=this;this.listener=c()(D,"click",function($e){return Y.onClick($e)})}},{key:"onClick",value:function(D){var Y=D.delegateTarget||D.currentTarget,$e=this.action(Y)||"copy",Dt=qe({action:$e,container:this.container,target:this.target(Y),text:this.text(Y)});this.emit(Dt?"success":"error",{action:$e,text:Dt,trigger:Y,clearSelection:function(){Y&&Y.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(D){return vr("action",D)}},{key:"defaultTarget",value:function(D){var Y=vr("target",D);if(Y)return document.querySelector(Y)}},{key:"defaultText",value:function(D){return vr("text",D)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(D){var Y=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return J(D,Y)}},{key:"cut",value:function(D){return y(D)}},{key:"isSupported",value:function(){var D=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],Y=typeof D=="string"?[D]:D,$e=!!document.queryCommandSupported;return Y.forEach(function(Dt){$e=$e&&!!document.queryCommandSupported(Dt)}),$e}}]),M}(s()),Ui=Fi},828:function(o){var n=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,p){for(;s&&s.nodeType!==n;){if(typeof s.matches=="function"&&s.matches(p))return s;s=s.parentNode}}o.exports=a},438:function(o,n,i){var a=i(828);function s(l,f,u,d,y){var L=c.apply(this,arguments);return l.addEventListener(u,L,y),{destroy:function(){l.removeEventListener(u,L,y)}}}function p(l,f,u,d,y){return typeof l.addEventListener=="function"?s.apply(null,arguments):typeof u=="function"?s.bind(null,document).apply(null,arguments):(typeof l=="string"&&(l=document.querySelectorAll(l)),Array.prototype.map.call(l,function(L){return s(L,f,u,d,y)}))}function c(l,f,u,d){return function(y){y.delegateTarget=a(y.target,f),y.delegateTarget&&d.call(l,y)}}o.exports=p},879:function(o,n){n.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},n.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||n.node(i[0]))},n.string=function(i){return typeof i=="string"||i instanceof String},n.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(o,n,i){var a=i(879),s=i(438);function p(u,d,y){if(!u&&!d&&!y)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(y))throw new TypeError("Third argument must be a Function");if(a.node(u))return c(u,d,y);if(a.nodeList(u))return l(u,d,y);if(a.string(u))return f(u,d,y);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(u,d,y){return u.addEventListener(d,y),{destroy:function(){u.removeEventListener(d,y)}}}function l(u,d,y){return Array.prototype.forEach.call(u,function(L){L.addEventListener(d,y)}),{destroy:function(){Array.prototype.forEach.call(u,function(L){L.removeEventListener(d,y)})}}}function f(u,d,y){return s(document.body,u,d,y)}o.exports=p},817:function(o){function n(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var p=window.getSelection(),c=document.createRange();c.selectNodeContents(i),p.removeAllRanges(),p.addRange(c),a=p.toString()}return a}o.exports=n},279:function(o){function n(){}n.prototype={on:function(i,a,s){var p=this.e||(this.e={});return(p[i]||(p[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var p=this;function c(){p.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),p=0,c=s.length;for(p;p0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function N(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var o=r.call(e),n,i=[],a;try{for(;(t===void 0||t-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(s){a={error:s}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(a)throw a.error}}return i}function q(e,t,r){if(r||arguments.length===2)for(var o=0,n=t.length,i;o1||p(d,L)})},y&&(n[d]=y(n[d])))}function p(d,y){try{c(o[d](y))}catch(L){u(i[0][3],L)}}function c(d){d.value instanceof nt?Promise.resolve(d.value.v).then(l,f):u(i[0][2],d)}function l(d){p("next",d)}function f(d){p("throw",d)}function u(d,y){d(y),i.shift(),i.length&&p(i[0][0],i[0][1])}}function uo(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof he=="function"?he(e):e[Symbol.iterator](),r={},o("next"),o("throw"),o("return"),r[Symbol.asyncIterator]=function(){return this},r);function o(i){r[i]=e[i]&&function(a){return new Promise(function(s,p){a=e[i](a),n(s,p,a.done,a.value)})}}function n(i,a,s,p){Promise.resolve(p).then(function(c){i({value:c,done:s})},a)}}function H(e){return typeof e=="function"}function ut(e){var t=function(o){Error.call(o),o.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var zt=ut(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(o,n){return n+1+") "+o.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Qe(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ue=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,o,n,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=he(a),p=s.next();!p.done;p=s.next()){var c=p.value;c.remove(this)}}catch(L){t={error:L}}finally{try{p&&!p.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var l=this.initialTeardown;if(H(l))try{l()}catch(L){i=L instanceof zt?L.errors:[L]}var f=this._finalizers;if(f){this._finalizers=null;try{for(var u=he(f),d=u.next();!d.done;d=u.next()){var y=d.value;try{ho(y)}catch(L){i=i!=null?i:[],L instanceof zt?i=q(q([],N(i)),N(L.errors)):i.push(L)}}}catch(L){o={error:L}}finally{try{d&&!d.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}}if(i)throw new zt(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)ho(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Qe(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Qe(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Tr=Ue.EMPTY;function qt(e){return e instanceof Ue||e&&"closed"in e&&H(e.remove)&&H(e.add)&&H(e.unsubscribe)}function ho(e){H(e)?e():e.unsubscribe()}var Pe={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var dt={setTimeout:function(e,t){for(var r=[],o=2;o0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var o=this,n=this,i=n.hasError,a=n.isStopped,s=n.observers;return i||a?Tr:(this.currentObservers=null,s.push(r),new Ue(function(){o.currentObservers=null,Qe(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var o=this,n=o.hasError,i=o.thrownError,a=o.isStopped;n?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new j;return r.source=this,r},t.create=function(r,o){return new To(r,o)},t}(j);var To=function(e){oe(t,e);function t(r,o){var n=e.call(this)||this;return n.destination=r,n.source=o,n}return t.prototype.next=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.next)===null||n===void 0||n.call(o,r)},t.prototype.error=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.error)===null||n===void 0||n.call(o,r)},t.prototype.complete=function(){var r,o;(o=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||o===void 0||o.call(r)},t.prototype._subscribe=function(r){var o,n;return(n=(o=this.source)===null||o===void 0?void 0:o.subscribe(r))!==null&&n!==void 0?n:Tr},t}(g);var _r=function(e){oe(t,e);function t(r){var o=e.call(this)||this;return o._value=r,o}return Object.defineProperty(t.prototype,"value",{get:function(){return this.getValue()},enumerable:!1,configurable:!0}),t.prototype._subscribe=function(r){var o=e.prototype._subscribe.call(this,r);return!o.closed&&r.next(this._value),o},t.prototype.getValue=function(){var r=this,o=r.hasError,n=r.thrownError,i=r._value;if(o)throw n;return this._throwIfClosed(),i},t.prototype.next=function(r){e.prototype.next.call(this,this._value=r)},t}(g);var At={now:function(){return(At.delegate||Date).now()},delegate:void 0};var Ct=function(e){oe(t,e);function t(r,o,n){r===void 0&&(r=1/0),o===void 0&&(o=1/0),n===void 0&&(n=At);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=o,i._timestampProvider=n,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=o===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,o),i}return t.prototype.next=function(r){var o=this,n=o.isStopped,i=o._buffer,a=o._infiniteTimeWindow,s=o._timestampProvider,p=o._windowTime;n||(i.push(r),!a&&i.push(s.now()+p)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var o=this._innerSubscribe(r),n=this,i=n._infiniteTimeWindow,a=n._buffer,s=a.slice(),p=0;p0?e.prototype.schedule.call(this,r,o):(this.delay=o,this.state=r,this.scheduler.flush(this),this)},t.prototype.execute=function(r,o){return o>0||this.closed?e.prototype.execute.call(this,r,o):this._execute(r,o)},t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!=null&&n>0||n==null&&this.delay>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.flush(this),0)},t}(gt);var Lo=function(e){oe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t}(yt);var kr=new Lo(Oo);var Mo=function(e){oe(t,e);function t(r,o){var n=e.call(this,r,o)||this;return n.scheduler=r,n.work=o,n}return t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!==null&&n>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.actions.push(this),r._scheduled||(r._scheduled=vt.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,o,n){var i;if(n===void 0&&(n=0),n!=null?n>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,o,n);var a=r.actions;o!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==o&&(vt.cancelAnimationFrame(o),r._scheduled=void 0)},t}(gt);var _o=function(e){oe(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var o=this._scheduled;this._scheduled=void 0;var n=this.actions,i;r=r||n.shift();do if(i=r.execute(r.state,r.delay))break;while((r=n[0])&&r.id===o&&n.shift());if(this._active=!1,i){for(;(r=n[0])&&r.id===o&&n.shift();)r.unsubscribe();throw i}},t}(yt);var me=new _o(Mo);var S=new j(function(e){return e.complete()});function Yt(e){return e&&H(e.schedule)}function Hr(e){return e[e.length-1]}function Xe(e){return H(Hr(e))?e.pop():void 0}function ke(e){return Yt(Hr(e))?e.pop():void 0}function Bt(e,t){return typeof Hr(e)=="number"?e.pop():t}var xt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Gt(e){return H(e==null?void 0:e.then)}function Jt(e){return H(e[bt])}function Xt(e){return Symbol.asyncIterator&&H(e==null?void 0:e[Symbol.asyncIterator])}function Zt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Zi(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var er=Zi();function tr(e){return H(e==null?void 0:e[er])}function rr(e){return fo(this,arguments,function(){var r,o,n,i;return Nt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,nt(r.read())];case 3:return o=a.sent(),n=o.value,i=o.done,i?[4,nt(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,nt(n)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function or(e){return H(e==null?void 0:e.getReader)}function U(e){if(e instanceof j)return e;if(e!=null){if(Jt(e))return ea(e);if(xt(e))return ta(e);if(Gt(e))return ra(e);if(Xt(e))return Ao(e);if(tr(e))return oa(e);if(or(e))return na(e)}throw Zt(e)}function ea(e){return new j(function(t){var r=e[bt]();if(H(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function ta(e){return new j(function(t){for(var r=0;r=2;return function(o){return o.pipe(e?b(function(n,i){return e(n,i,o)}):le,Te(1),r?De(t):Qo(function(){return new ir}))}}function jr(e){return e<=0?function(){return S}:E(function(t,r){var o=[];t.subscribe(T(r,function(n){o.push(n),e=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new g}:t,o=e.resetOnError,n=o===void 0?!0:o,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,p=s===void 0?!0:s;return function(c){var l,f,u,d=0,y=!1,L=!1,X=function(){f==null||f.unsubscribe(),f=void 0},te=function(){X(),l=u=void 0,y=L=!1},J=function(){var k=l;te(),k==null||k.unsubscribe()};return E(function(k,ft){d++,!L&&!y&&X();var qe=u=u!=null?u:r();ft.add(function(){d--,d===0&&!L&&!y&&(f=Ur(J,p))}),qe.subscribe(ft),!l&&d>0&&(l=new at({next:function(Fe){return qe.next(Fe)},error:function(Fe){L=!0,X(),f=Ur(te,n,Fe),qe.error(Fe)},complete:function(){y=!0,X(),f=Ur(te,a),qe.complete()}}),U(k).subscribe(l))})(c)}}function Ur(e,t){for(var r=[],o=2;oe.next(document)),e}function P(e,t=document){return Array.from(t.querySelectorAll(e))}function R(e,t=document){let r=fe(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function fe(e,t=document){return t.querySelector(e)||void 0}function Ie(){var e,t,r,o;return(o=(r=(t=(e=document.activeElement)==null?void 0:e.shadowRoot)==null?void 0:t.activeElement)!=null?r:document.activeElement)!=null?o:void 0}var wa=O(h(document.body,"focusin"),h(document.body,"focusout")).pipe(_e(1),Q(void 0),m(()=>Ie()||document.body),G(1));function et(e){return wa.pipe(m(t=>e.contains(t)),K())}function $t(e,t){return C(()=>O(h(e,"mouseenter").pipe(m(()=>!0)),h(e,"mouseleave").pipe(m(()=>!1))).pipe(t?Ht(r=>Le(+!r*t)):le,Q(e.matches(":hover"))))}function Jo(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)Jo(e,r)}function x(e,t,...r){let o=document.createElement(e);if(t)for(let n of Object.keys(t))typeof t[n]!="undefined"&&(typeof t[n]!="boolean"?o.setAttribute(n,t[n]):o.setAttribute(n,""));for(let n of r)Jo(o,n);return o}function sr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function Tt(e){let t=x("script",{src:e});return C(()=>(document.head.appendChild(t),O(h(t,"load"),h(t,"error").pipe(v(()=>$r(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(m(()=>{}),_(()=>document.head.removeChild(t)),Te(1))))}var Xo=new g,Ta=C(()=>typeof ResizeObserver=="undefined"?Tt("https://unpkg.com/resize-observer-polyfill"):I(void 0)).pipe(m(()=>new ResizeObserver(e=>e.forEach(t=>Xo.next(t)))),v(e=>O(Ye,I(e)).pipe(_(()=>e.disconnect()))),G(1));function ce(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){let t=e;for(;t.clientWidth===0&&t.parentElement;)t=t.parentElement;return Ta.pipe(w(r=>r.observe(t)),v(r=>Xo.pipe(b(o=>o.target===t),_(()=>r.unobserve(t)))),m(()=>ce(e)),Q(ce(e)))}function St(e){return{width:e.scrollWidth,height:e.scrollHeight}}function cr(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}function Zo(e){let t=[],r=e.parentElement;for(;r;)(e.clientWidth>r.clientWidth||e.clientHeight>r.clientHeight)&&t.push(r),r=(e=r).parentElement;return t.length===0&&t.push(document.documentElement),t}function Ve(e){return{x:e.offsetLeft,y:e.offsetTop}}function en(e){let t=e.getBoundingClientRect();return{x:t.x+window.scrollX,y:t.y+window.scrollY}}function tn(e){return O(h(window,"load"),h(window,"resize")).pipe(Me(0,me),m(()=>Ve(e)),Q(Ve(e)))}function pr(e){return{x:e.scrollLeft,y:e.scrollTop}}function Ne(e){return O(h(e,"scroll"),h(window,"scroll"),h(window,"resize")).pipe(Me(0,me),m(()=>pr(e)),Q(pr(e)))}var rn=new g,Sa=C(()=>I(new IntersectionObserver(e=>{for(let t of e)rn.next(t)},{threshold:0}))).pipe(v(e=>O(Ye,I(e)).pipe(_(()=>e.disconnect()))),G(1));function tt(e){return Sa.pipe(w(t=>t.observe(e)),v(t=>rn.pipe(b(({target:r})=>r===e),_(()=>t.unobserve(e)),m(({isIntersecting:r})=>r))))}function on(e,t=16){return Ne(e).pipe(m(({y:r})=>{let o=ce(e),n=St(e);return r>=n.height-o.height-t}),K())}var lr={drawer:R("[data-md-toggle=drawer]"),search:R("[data-md-toggle=search]")};function nn(e){return lr[e].checked}function Je(e,t){lr[e].checked!==t&&lr[e].click()}function ze(e){let t=lr[e];return h(t,"change").pipe(m(()=>t.checked),Q(t.checked))}function Oa(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function La(){return O(h(window,"compositionstart").pipe(m(()=>!0)),h(window,"compositionend").pipe(m(()=>!1))).pipe(Q(!1))}function an(){let e=h(window,"keydown").pipe(b(t=>!(t.metaKey||t.ctrlKey)),m(t=>({mode:nn("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),b(({mode:t,type:r})=>{if(t==="global"){let o=Ie();if(typeof o!="undefined")return!Oa(o,r)}return!0}),pe());return La().pipe(v(t=>t?S:e))}function ye(){return new URL(location.href)}function lt(e,t=!1){if(B("navigation.instant")&&!t){let r=x("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function sn(){return new g}function cn(){return location.hash.slice(1)}function pn(e){let t=x("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Ma(e){return O(h(window,"hashchange"),e).pipe(m(cn),Q(cn()),b(t=>t.length>0),G(1))}function ln(e){return Ma(e).pipe(m(t=>fe(`[id="${t}"]`)),b(t=>typeof t!="undefined"))}function Pt(e){let t=matchMedia(e);return ar(r=>t.addListener(()=>r(t.matches))).pipe(Q(t.matches))}function mn(){let e=matchMedia("print");return O(h(window,"beforeprint").pipe(m(()=>!0)),h(window,"afterprint").pipe(m(()=>!1))).pipe(Q(e.matches))}function Nr(e,t){return e.pipe(v(r=>r?t():S))}function zr(e,t){return new j(r=>{let o=new XMLHttpRequest;return o.open("GET",`${e}`),o.responseType="blob",o.addEventListener("load",()=>{o.status>=200&&o.status<300?(r.next(o.response),r.complete()):r.error(new Error(o.statusText))}),o.addEventListener("error",()=>{r.error(new Error("Network error"))}),o.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(o.addEventListener("progress",n=>{var i;if(n.lengthComputable)t.progress$.next(n.loaded/n.total*100);else{let a=(i=o.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(n.loaded/+a*100)}}),t.progress$.next(5)),o.send(),()=>o.abort()})}function je(e,t){return zr(e,t).pipe(v(r=>r.text()),m(r=>JSON.parse(r)),G(1))}function fn(e,t){let r=new DOMParser;return zr(e,t).pipe(v(o=>o.text()),m(o=>r.parseFromString(o,"text/html")),G(1))}function un(e,t){let r=new DOMParser;return zr(e,t).pipe(v(o=>o.text()),m(o=>r.parseFromString(o,"text/xml")),G(1))}function dn(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function hn(){return O(h(window,"scroll",{passive:!0}),h(window,"resize",{passive:!0})).pipe(m(dn),Q(dn()))}function bn(){return{width:innerWidth,height:innerHeight}}function vn(){return h(window,"resize",{passive:!0}).pipe(m(bn),Q(bn()))}function gn(){return z([hn(),vn()]).pipe(m(([e,t])=>({offset:e,size:t})),G(1))}function mr(e,{viewport$:t,header$:r}){let o=t.pipe(ee("size")),n=z([o,r]).pipe(m(()=>Ve(e)));return z([r,t,n]).pipe(m(([{height:i},{offset:a,size:s},{x:p,y:c}])=>({offset:{x:a.x-p,y:a.y-c+i},size:s})))}function _a(e){return h(e,"message",t=>t.data)}function Aa(e){let t=new g;return t.subscribe(r=>e.postMessage(r)),t}function yn(e,t=new Worker(e)){let r=_a(t),o=Aa(t),n=new g;n.subscribe(o);let i=o.pipe(Z(),ie(!0));return n.pipe(Z(),Re(r.pipe(W(i))),pe())}var Ca=R("#__config"),Ot=JSON.parse(Ca.textContent);Ot.base=`${new URL(Ot.base,ye())}`;function xe(){return Ot}function B(e){return Ot.features.includes(e)}function Ee(e,t){return typeof t!="undefined"?Ot.translations[e].replace("#",t.toString()):Ot.translations[e]}function Se(e,t=document){return R(`[data-md-component=${e}]`,t)}function ae(e,t=document){return P(`[data-md-component=${e}]`,t)}function ka(e){let t=R(".md-typeset > :first-child",e);return h(t,"click",{once:!0}).pipe(m(()=>R(".md-typeset",e)),m(r=>({hash:__md_hash(r.innerHTML)})))}function xn(e){if(!B("announce.dismiss")||!e.childElementCount)return S;if(!e.hidden){let t=R(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return C(()=>{let t=new g;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),ka(e).pipe(w(r=>t.next(r)),_(()=>t.complete()),m(r=>$({ref:e},r)))})}function Ha(e,{target$:t}){return t.pipe(m(r=>({hidden:r!==e})))}function En(e,t){let r=new g;return r.subscribe(({hidden:o})=>{e.hidden=o}),Ha(e,t).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))}function Rt(e,t){return t==="inline"?x("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"})):x("div",{class:"md-tooltip",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"}))}function wn(...e){return x("div",{class:"md-tooltip2",role:"tooltip"},x("div",{class:"md-tooltip2__inner md-typeset"},e))}function Tn(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return x("aside",{class:"md-annotation",tabIndex:0},Rt(t),x("a",{href:r,class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}else return x("aside",{class:"md-annotation",tabIndex:0},Rt(t),x("span",{class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}function Sn(e){return x("button",{class:"md-clipboard md-icon",title:Ee("clipboard.copy"),"data-clipboard-target":`#${e} > code`})}var Ln=Mt(qr());function Qr(e,t){let r=t&2,o=t&1,n=Object.keys(e.terms).filter(p=>!e.terms[p]).reduce((p,c)=>[...p,x("del",null,(0,Ln.default)(c))," "],[]).slice(0,-1),i=xe(),a=new URL(e.location,i.base);B("search.highlight")&&a.searchParams.set("h",Object.entries(e.terms).filter(([,p])=>p).reduce((p,[c])=>`${p} ${c}`.trim(),""));let{tags:s}=xe();return x("a",{href:`${a}`,class:"md-search-result__link",tabIndex:-1},x("article",{class:"md-search-result__article md-typeset","data-md-score":e.score.toFixed(2)},r>0&&x("div",{class:"md-search-result__icon md-icon"}),r>0&&x("h1",null,e.title),r<=0&&x("h2",null,e.title),o>0&&e.text.length>0&&e.text,e.tags&&x("nav",{class:"md-tags"},e.tags.map(p=>{let c=s?p in s?`md-tag-icon md-tag--${s[p]}`:"md-tag-icon":"";return x("span",{class:`md-tag ${c}`},p)})),o>0&&n.length>0&&x("p",{class:"md-search-result__terms"},Ee("search.result.term.missing"),": ",...n)))}function Mn(e){let t=e[0].score,r=[...e],o=xe(),n=r.findIndex(l=>!`${new URL(l.location,o.base)}`.includes("#")),[i]=r.splice(n,1),a=r.findIndex(l=>l.scoreQr(l,1)),...p.length?[x("details",{class:"md-search-result__more"},x("summary",{tabIndex:-1},x("div",null,p.length>0&&p.length===1?Ee("search.result.more.one"):Ee("search.result.more.other",p.length))),...p.map(l=>Qr(l,1)))]:[]];return x("li",{class:"md-search-result__item"},c)}function _n(e){return x("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>x("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?sr(r):r)))}function Kr(e){let t=`tabbed-control tabbed-control--${e}`;return x("div",{class:t,hidden:!0},x("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function An(e){return x("div",{class:"md-typeset__scrollwrap"},x("div",{class:"md-typeset__table"},e))}function Ra(e){var o;let t=xe(),r=new URL(`../${e.version}/`,t.base);return x("li",{class:"md-version__item"},x("a",{href:`${r}`,class:"md-version__link"},e.title,((o=t.version)==null?void 0:o.alias)&&e.aliases.length>0&&x("span",{class:"md-version__alias"},e.aliases[0])))}function Cn(e,t){var o;let r=xe();return e=e.filter(n=>{var i;return!((i=n.properties)!=null&&i.hidden)}),x("div",{class:"md-version"},x("button",{class:"md-version__current","aria-label":Ee("select.version")},t.title,((o=r.version)==null?void 0:o.alias)&&t.aliases.length>0&&x("span",{class:"md-version__alias"},t.aliases[0])),x("ul",{class:"md-version__list"},e.map(Ra)))}var Ia=0;function ja(e){let t=z([et(e),$t(e)]).pipe(m(([o,n])=>o||n),K()),r=C(()=>Zo(e)).pipe(ne(Ne),pt(1),He(t),m(()=>en(e)));return t.pipe(Ae(o=>o),v(()=>z([t,r])),m(([o,n])=>({active:o,offset:n})),pe())}function Fa(e,t){let{content$:r,viewport$:o}=t,n=`__tooltip2_${Ia++}`;return C(()=>{let i=new g,a=new _r(!1);i.pipe(Z(),ie(!1)).subscribe(a);let s=a.pipe(Ht(c=>Le(+!c*250,kr)),K(),v(c=>c?r:S),w(c=>c.id=n),pe());z([i.pipe(m(({active:c})=>c)),s.pipe(v(c=>$t(c,250)),Q(!1))]).pipe(m(c=>c.some(l=>l))).subscribe(a);let p=a.pipe(b(c=>c),re(s,o),m(([c,l,{size:f}])=>{let u=e.getBoundingClientRect(),d=u.width/2;if(l.role==="tooltip")return{x:d,y:8+u.height};if(u.y>=f.height/2){let{height:y}=ce(l);return{x:d,y:-16-y}}else return{x:d,y:16+u.height}}));return z([s,i,p]).subscribe(([c,{offset:l},f])=>{c.style.setProperty("--md-tooltip-host-x",`${l.x}px`),c.style.setProperty("--md-tooltip-host-y",`${l.y}px`),c.style.setProperty("--md-tooltip-x",`${f.x}px`),c.style.setProperty("--md-tooltip-y",`${f.y}px`),c.classList.toggle("md-tooltip2--top",f.y<0),c.classList.toggle("md-tooltip2--bottom",f.y>=0)}),a.pipe(b(c=>c),re(s,(c,l)=>l),b(c=>c.role==="tooltip")).subscribe(c=>{let l=ce(R(":scope > *",c));c.style.setProperty("--md-tooltip-width",`${l.width}px`),c.style.setProperty("--md-tooltip-tail","0px")}),a.pipe(K(),ve(me),re(s)).subscribe(([c,l])=>{l.classList.toggle("md-tooltip2--active",c)}),z([a.pipe(b(c=>c)),s]).subscribe(([c,l])=>{l.role==="dialog"?(e.setAttribute("aria-controls",n),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",n)}),a.pipe(b(c=>!c)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),ja(e).pipe(w(c=>i.next(c)),_(()=>i.complete()),m(c=>$({ref:e},c)))})}function mt(e,{viewport$:t},r=document.body){return Fa(e,{content$:new j(o=>{let n=e.title,i=wn(n);return o.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",n)}}),viewport$:t})}function Ua(e,t){let r=C(()=>z([tn(e),Ne(t)])).pipe(m(([{x:o,y:n},i])=>{let{width:a,height:s}=ce(e);return{x:o-i.x+a/2,y:n-i.y+s/2}}));return et(e).pipe(v(o=>r.pipe(m(n=>({active:o,offset:n})),Te(+!o||1/0))))}function kn(e,t,{target$:r}){let[o,n]=Array.from(e.children);return C(()=>{let i=new g,a=i.pipe(Z(),ie(!0));return i.subscribe({next({offset:s}){e.style.setProperty("--md-tooltip-x",`${s.x}px`),e.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),tt(e).pipe(W(a)).subscribe(s=>{e.toggleAttribute("data-md-visible",s)}),O(i.pipe(b(({active:s})=>s)),i.pipe(_e(250),b(({active:s})=>!s))).subscribe({next({active:s}){s?e.prepend(o):o.remove()},complete(){e.prepend(o)}}),i.pipe(Me(16,me)).subscribe(({active:s})=>{o.classList.toggle("md-tooltip--active",s)}),i.pipe(pt(125,me),b(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:s})=>s)).subscribe({next(s){s?e.style.setProperty("--md-tooltip-0",`${-s}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),h(n,"click").pipe(W(a),b(s=>!(s.metaKey||s.ctrlKey))).subscribe(s=>{s.stopPropagation(),s.preventDefault()}),h(n,"mousedown").pipe(W(a),re(i)).subscribe(([s,{active:p}])=>{var c;if(s.button!==0||s.metaKey||s.ctrlKey)s.preventDefault();else if(p){s.preventDefault();let l=e.parentElement.closest(".md-annotation");l instanceof HTMLElement?l.focus():(c=Ie())==null||c.blur()}}),r.pipe(W(a),b(s=>s===o),Ge(125)).subscribe(()=>e.focus()),Ua(e,t).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))})}function Wa(e){return e.tagName==="CODE"?P(".c, .c1, .cm",e):[e]}function Da(e){let t=[];for(let r of Wa(e)){let o=[],n=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=n.nextNode();i;i=n.nextNode())o.push(i);for(let i of o){let a;for(;a=/(\(\d+\))(!)?/.exec(i.textContent);){let[,s,p]=a;if(typeof p=="undefined"){let c=i.splitText(a.index);i=c.splitText(s.length),t.push(c)}else{i.textContent=s,t.push(i);break}}}}return t}function Hn(e,t){t.append(...Array.from(e.childNodes))}function fr(e,t,{target$:r,print$:o}){let n=t.closest("[id]"),i=n==null?void 0:n.id,a=new Map;for(let s of Da(t)){let[,p]=s.textContent.match(/\((\d+)\)/);fe(`:scope > li:nth-child(${p})`,e)&&(a.set(p,Tn(p,i)),s.replaceWith(a.get(p)))}return a.size===0?S:C(()=>{let s=new g,p=s.pipe(Z(),ie(!0)),c=[];for(let[l,f]of a)c.push([R(".md-typeset",f),R(`:scope > li:nth-child(${l})`,e)]);return o.pipe(W(p)).subscribe(l=>{e.hidden=!l,e.classList.toggle("md-annotation-list",l);for(let[f,u]of c)l?Hn(f,u):Hn(u,f)}),O(...[...a].map(([,l])=>kn(l,t,{target$:r}))).pipe(_(()=>s.complete()),pe())})}function $n(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return $n(t)}}function Pn(e,t){return C(()=>{let r=$n(e);return typeof r!="undefined"?fr(r,e,t):S})}var Rn=Mt(Br());var Va=0;function In(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return In(t)}}function Na(e){return ge(e).pipe(m(({width:t})=>({scrollable:St(e).width>t})),ee("scrollable"))}function jn(e,t){let{matches:r}=matchMedia("(hover)"),o=C(()=>{let n=new g,i=n.pipe(jr(1));n.subscribe(({scrollable:c})=>{c&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let a=[];if(Rn.default.isSupported()&&(e.closest(".copy")||B("content.code.copy")&&!e.closest(".no-copy"))){let c=e.closest("pre");c.id=`__code_${Va++}`;let l=Sn(c.id);c.insertBefore(l,e),B("content.tooltips")&&a.push(mt(l,{viewport$}))}let s=e.closest(".highlight");if(s instanceof HTMLElement){let c=In(s);if(typeof c!="undefined"&&(s.classList.contains("annotate")||B("content.code.annotate"))){let l=fr(c,e,t);a.push(ge(s).pipe(W(i),m(({width:f,height:u})=>f&&u),K(),v(f=>f?l:S)))}}return P(":scope > span[id]",e).length&&e.classList.add("md-code__content"),Na(e).pipe(w(c=>n.next(c)),_(()=>n.complete()),m(c=>$({ref:e},c)),Re(...a))});return B("content.lazy")?tt(e).pipe(b(n=>n),Te(1),v(()=>o)):o}function za(e,{target$:t,print$:r}){let o=!0;return O(t.pipe(m(n=>n.closest("details:not([open])")),b(n=>e===n),m(()=>({action:"open",reveal:!0}))),r.pipe(b(n=>n||!o),w(()=>o=e.open),m(n=>({action:n?"open":"close"}))))}function Fn(e,t){return C(()=>{let r=new g;return r.subscribe(({action:o,reveal:n})=>{e.toggleAttribute("open",o==="open"),n&&e.scrollIntoView()}),za(e,t).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}var Un=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.flowchartTitleText{fill:var(--md-mermaid-label-fg-color)}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel p,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel p{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color);stroke-width:.05rem}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}.classDiagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs #classDiagram-compositionEnd,defs #classDiagram-compositionStart,defs #classDiagram-dependencyEnd,defs #classDiagram-dependencyStart,defs #classDiagram-extensionEnd,defs #classDiagram-extensionStart{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs #classDiagram-aggregationEnd,defs #classDiagram-aggregationStart{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}.statediagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}.entityTitleText{fill:var(--md-mermaid-label-fg-color)}.attributeBoxEven,.attributeBoxOdd{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityBox{fill:var(--md-mermaid-label-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityLabel{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.relationshipLabelBox{fill:var(--md-mermaid-label-bg-color);fill-opacity:1;background-color:var(--md-mermaid-label-bg-color);opacity:1}.relationshipLabel{fill:var(--md-mermaid-label-fg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs #ONE_OR_MORE_END *,defs #ONE_OR_MORE_START *,defs #ONLY_ONE_END *,defs #ONLY_ONE_START *,defs #ZERO_OR_MORE_END *,defs #ZERO_OR_MORE_START *,defs #ZERO_OR_ONE_END *,defs #ZERO_OR_ONE_START *{stroke:var(--md-mermaid-edge-color)!important}defs #ZERO_OR_MORE_END circle,defs #ZERO_OR_MORE_START circle{fill:var(--md-mermaid-label-bg-color)}text:not([class]):last-child{fill:var(--md-mermaid-label-fg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var Gr,Qa=0;function Ka(){return typeof mermaid=="undefined"||mermaid instanceof Element?Tt("https://unpkg.com/mermaid@11/dist/mermaid.min.js"):I(void 0)}function Wn(e){return e.classList.remove("mermaid"),Gr||(Gr=Ka().pipe(w(()=>mermaid.initialize({startOnLoad:!1,themeCSS:Un,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),m(()=>{}),G(1))),Gr.subscribe(()=>co(this,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${Qa++}`,r=x("div",{class:"mermaid"}),o=e.textContent,{svg:n,fn:i}=yield mermaid.render(t,o),a=r.attachShadow({mode:"closed"});a.innerHTML=n,e.replaceWith(r),i==null||i(a)})),Gr.pipe(m(()=>({ref:e})))}var Dn=x("table");function Vn(e){return e.replaceWith(Dn),Dn.replaceWith(An(e)),I({ref:e})}function Ya(e){let t=e.find(r=>r.checked)||e[0];return O(...e.map(r=>h(r,"change").pipe(m(()=>R(`label[for="${r.id}"]`))))).pipe(Q(R(`label[for="${t.id}"]`)),m(r=>({active:r})))}function Nn(e,{viewport$:t,target$:r}){let o=R(".tabbed-labels",e),n=P(":scope > input",e),i=Kr("prev");e.append(i);let a=Kr("next");return e.append(a),C(()=>{let s=new g,p=s.pipe(Z(),ie(!0));z([s,ge(e),tt(e)]).pipe(W(p),Me(1,me)).subscribe({next([{active:c},l]){let f=Ve(c),{width:u}=ce(c);e.style.setProperty("--md-indicator-x",`${f.x}px`),e.style.setProperty("--md-indicator-width",`${u}px`);let d=pr(o);(f.xd.x+l.width)&&o.scrollTo({left:Math.max(0,f.x-16),behavior:"smooth"})},complete(){e.style.removeProperty("--md-indicator-x"),e.style.removeProperty("--md-indicator-width")}}),z([Ne(o),ge(o)]).pipe(W(p)).subscribe(([c,l])=>{let f=St(o);i.hidden=c.x<16,a.hidden=c.x>f.width-l.width-16}),O(h(i,"click").pipe(m(()=>-1)),h(a,"click").pipe(m(()=>1))).pipe(W(p)).subscribe(c=>{let{width:l}=ce(o);o.scrollBy({left:l*c,behavior:"smooth"})}),r.pipe(W(p),b(c=>n.includes(c))).subscribe(c=>c.click()),o.classList.add("tabbed-labels--linked");for(let c of n){let l=R(`label[for="${c.id}"]`);l.replaceChildren(x("a",{href:`#${l.htmlFor}`,tabIndex:-1},...Array.from(l.childNodes))),h(l.firstElementChild,"click").pipe(W(p),b(f=>!(f.metaKey||f.ctrlKey)),w(f=>{f.preventDefault(),f.stopPropagation()})).subscribe(()=>{history.replaceState({},"",`#${l.htmlFor}`),l.click()})}return B("content.tabs.link")&&s.pipe(Ce(1),re(t)).subscribe(([{active:c},{offset:l}])=>{let f=c.innerText.trim();if(c.hasAttribute("data-md-switching"))c.removeAttribute("data-md-switching");else{let u=e.offsetTop-l.y;for(let y of P("[data-tabs]"))for(let L of P(":scope > input",y)){let X=R(`label[for="${L.id}"]`);if(X!==c&&X.innerText.trim()===f){X.setAttribute("data-md-switching",""),L.click();break}}window.scrollTo({top:e.offsetTop-u});let d=__md_get("__tabs")||[];__md_set("__tabs",[...new Set([f,...d])])}}),s.pipe(W(p)).subscribe(()=>{for(let c of P("audio, video",e))c.pause()}),Ya(n).pipe(w(c=>s.next(c)),_(()=>s.complete()),m(c=>$({ref:e},c)))}).pipe(Ke(se))}function zn(e,{viewport$:t,target$:r,print$:o}){return O(...P(".annotate:not(.highlight)",e).map(n=>Pn(n,{target$:r,print$:o})),...P("pre:not(.mermaid) > code",e).map(n=>jn(n,{target$:r,print$:o})),...P("pre.mermaid",e).map(n=>Wn(n)),...P("table:not([class])",e).map(n=>Vn(n)),...P("details",e).map(n=>Fn(n,{target$:r,print$:o})),...P("[data-tabs]",e).map(n=>Nn(n,{viewport$:t,target$:r})),...P("[title]",e).filter(()=>B("content.tooltips")).map(n=>mt(n,{viewport$:t})))}function Ba(e,{alert$:t}){return t.pipe(v(r=>O(I(!0),I(!1).pipe(Ge(2e3))).pipe(m(o=>({message:r,active:o})))))}function qn(e,t){let r=R(".md-typeset",e);return C(()=>{let o=new g;return o.subscribe(({message:n,active:i})=>{e.classList.toggle("md-dialog--active",i),r.textContent=n}),Ba(e,t).pipe(w(n=>o.next(n)),_(()=>o.complete()),m(n=>$({ref:e},n)))})}var Ga=0;function Ja(e,t){document.body.append(e);let{width:r}=ce(e);e.style.setProperty("--md-tooltip-width",`${r}px`),e.remove();let o=cr(t),n=typeof o!="undefined"?Ne(o):I({x:0,y:0}),i=O(et(t),$t(t)).pipe(K());return z([i,n]).pipe(m(([a,s])=>{let{x:p,y:c}=Ve(t),l=ce(t),f=t.closest("table");return f&&t.parentElement&&(p+=f.offsetLeft+t.parentElement.offsetLeft,c+=f.offsetTop+t.parentElement.offsetTop),{active:a,offset:{x:p-s.x+l.width/2-r/2,y:c-s.y+l.height+8}}}))}function Qn(e){let t=e.title;if(!t.length)return S;let r=`__tooltip_${Ga++}`,o=Rt(r,"inline"),n=R(".md-typeset",o);return n.innerHTML=t,C(()=>{let i=new g;return i.subscribe({next({offset:a}){o.style.setProperty("--md-tooltip-x",`${a.x}px`),o.style.setProperty("--md-tooltip-y",`${a.y}px`)},complete(){o.style.removeProperty("--md-tooltip-x"),o.style.removeProperty("--md-tooltip-y")}}),O(i.pipe(b(({active:a})=>a)),i.pipe(_e(250),b(({active:a})=>!a))).subscribe({next({active:a}){a?(e.insertAdjacentElement("afterend",o),e.setAttribute("aria-describedby",r),e.removeAttribute("title")):(o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t))},complete(){o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t)}}),i.pipe(Me(16,me)).subscribe(({active:a})=>{o.classList.toggle("md-tooltip--active",a)}),i.pipe(pt(125,me),b(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:a})=>a)).subscribe({next(a){a?o.style.setProperty("--md-tooltip-0",`${-a}px`):o.style.removeProperty("--md-tooltip-0")},complete(){o.style.removeProperty("--md-tooltip-0")}}),Ja(o,e).pipe(w(a=>i.next(a)),_(()=>i.complete()),m(a=>$({ref:e},a)))}).pipe(Ke(se))}function Xa({viewport$:e}){if(!B("header.autohide"))return I(!1);let t=e.pipe(m(({offset:{y:n}})=>n),Be(2,1),m(([n,i])=>[nMath.abs(i-n.y)>100),m(([,[n]])=>n),K()),o=ze("search");return z([e,o]).pipe(m(([{offset:n},i])=>n.y>400&&!i),K(),v(n=>n?r:I(!1)),Q(!1))}function Kn(e,t){return C(()=>z([ge(e),Xa(t)])).pipe(m(([{height:r},o])=>({height:r,hidden:o})),K((r,o)=>r.height===o.height&&r.hidden===o.hidden),G(1))}function Yn(e,{header$:t,main$:r}){return C(()=>{let o=new g,n=o.pipe(Z(),ie(!0));o.pipe(ee("active"),He(t)).subscribe(([{active:a},{hidden:s}])=>{e.classList.toggle("md-header--shadow",a&&!s),e.hidden=s});let i=ue(P("[title]",e)).pipe(b(()=>B("content.tooltips")),ne(a=>Qn(a)));return r.subscribe(o),t.pipe(W(n),m(a=>$({ref:e},a)),Re(i.pipe(W(n))))})}function Za(e,{viewport$:t,header$:r}){return mr(e,{viewport$:t,header$:r}).pipe(m(({offset:{y:o}})=>{let{height:n}=ce(e);return{active:o>=n}}),ee("active"))}function Bn(e,t){return C(()=>{let r=new g;r.subscribe({next({active:n}){e.classList.toggle("md-header__title--active",n)},complete(){e.classList.remove("md-header__title--active")}});let o=fe(".md-content h1");return typeof o=="undefined"?S:Za(o,t).pipe(w(n=>r.next(n)),_(()=>r.complete()),m(n=>$({ref:e},n)))})}function Gn(e,{viewport$:t,header$:r}){let o=r.pipe(m(({height:i})=>i),K()),n=o.pipe(v(()=>ge(e).pipe(m(({height:i})=>({top:e.offsetTop,bottom:e.offsetTop+i})),ee("bottom"))));return z([o,n,t]).pipe(m(([i,{top:a,bottom:s},{offset:{y:p},size:{height:c}}])=>(c=Math.max(0,c-Math.max(0,a-p,i)-Math.max(0,c+p-s)),{offset:a-i,height:c,active:a-i<=p})),K((i,a)=>i.offset===a.offset&&i.height===a.height&&i.active===a.active))}function es(e){let t=__md_get("__palette")||{index:e.findIndex(o=>matchMedia(o.getAttribute("data-md-color-media")).matches)},r=Math.max(0,Math.min(t.index,e.length-1));return I(...e).pipe(ne(o=>h(o,"change").pipe(m(()=>o))),Q(e[r]),m(o=>({index:e.indexOf(o),color:{media:o.getAttribute("data-md-color-media"),scheme:o.getAttribute("data-md-color-scheme"),primary:o.getAttribute("data-md-color-primary"),accent:o.getAttribute("data-md-color-accent")}})),G(1))}function Jn(e){let t=P("input",e),r=x("meta",{name:"theme-color"});document.head.appendChild(r);let o=x("meta",{name:"color-scheme"});document.head.appendChild(o);let n=Pt("(prefers-color-scheme: light)");return C(()=>{let i=new g;return i.subscribe(a=>{if(document.body.setAttribute("data-md-color-switching",""),a.color.media==="(prefers-color-scheme)"){let s=matchMedia("(prefers-color-scheme: light)"),p=document.querySelector(s.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");a.color.scheme=p.getAttribute("data-md-color-scheme"),a.color.primary=p.getAttribute("data-md-color-primary"),a.color.accent=p.getAttribute("data-md-color-accent")}for(let[s,p]of Object.entries(a.color))document.body.setAttribute(`data-md-color-${s}`,p);for(let s=0;sa.key==="Enter"),re(i,(a,s)=>s)).subscribe(({index:a})=>{a=(a+1)%t.length,t[a].click(),t[a].focus()}),i.pipe(m(()=>{let a=Se("header"),s=window.getComputedStyle(a);return o.content=s.colorScheme,s.backgroundColor.match(/\d+/g).map(p=>(+p).toString(16).padStart(2,"0")).join("")})).subscribe(a=>r.content=`#${a}`),i.pipe(ve(se)).subscribe(()=>{document.body.removeAttribute("data-md-color-switching")}),es(t).pipe(W(n.pipe(Ce(1))),ct(),w(a=>i.next(a)),_(()=>i.complete()),m(a=>$({ref:e},a)))})}function Xn(e,{progress$:t}){return C(()=>{let r=new g;return r.subscribe(({value:o})=>{e.style.setProperty("--md-progress-value",`${o}`)}),t.pipe(w(o=>r.next({value:o})),_(()=>r.complete()),m(o=>({ref:e,value:o})))})}var Jr=Mt(Br());function ts(e){e.setAttribute("data-md-copying","");let t=e.closest("[data-copy]"),r=t?t.getAttribute("data-copy"):e.innerText;return e.removeAttribute("data-md-copying"),r.trimEnd()}function Zn({alert$:e}){Jr.default.isSupported()&&new j(t=>{new Jr.default("[data-clipboard-target], [data-clipboard-text]",{text:r=>r.getAttribute("data-clipboard-text")||ts(R(r.getAttribute("data-clipboard-target")))}).on("success",r=>t.next(r))}).pipe(w(t=>{t.trigger.focus()}),m(()=>Ee("clipboard.copied"))).subscribe(e)}function ei(e,t){return e.protocol=t.protocol,e.hostname=t.hostname,e}function rs(e,t){let r=new Map;for(let o of P("url",e)){let n=R("loc",o),i=[ei(new URL(n.textContent),t)];r.set(`${i[0]}`,i);for(let a of P("[rel=alternate]",o)){let s=a.getAttribute("href");s!=null&&i.push(ei(new URL(s),t))}}return r}function ur(e){return un(new URL("sitemap.xml",e)).pipe(m(t=>rs(t,new URL(e))),de(()=>I(new Map)))}function os(e,t){if(!(e.target instanceof Element))return S;let r=e.target.closest("a");if(r===null)return S;if(r.target||e.metaKey||e.ctrlKey)return S;let o=new URL(r.href);return o.search=o.hash="",t.has(`${o}`)?(e.preventDefault(),I(new URL(r.href))):S}function ti(e){let t=new Map;for(let r of P(":scope > *",e.head))t.set(r.outerHTML,r);return t}function ri(e){for(let t of P("[href], [src]",e))for(let r of["href","src"]){let o=t.getAttribute(r);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){t[r]=t[r];break}}return I(e)}function ns(e){for(let o of["[data-md-component=announce]","[data-md-component=container]","[data-md-component=header-topic]","[data-md-component=outdated]","[data-md-component=logo]","[data-md-component=skip]",...B("navigation.tabs.sticky")?["[data-md-component=tabs]"]:[]]){let n=fe(o),i=fe(o,e);typeof n!="undefined"&&typeof i!="undefined"&&n.replaceWith(i)}let t=ti(document);for(let[o,n]of ti(e))t.has(o)?t.delete(o):document.head.appendChild(n);for(let o of t.values()){let n=o.getAttribute("name");n!=="theme-color"&&n!=="color-scheme"&&o.remove()}let r=Se("container");return We(P("script",r)).pipe(v(o=>{let n=e.createElement("script");if(o.src){for(let i of o.getAttributeNames())n.setAttribute(i,o.getAttribute(i));return o.replaceWith(n),new j(i=>{n.onload=()=>i.complete()})}else return n.textContent=o.textContent,o.replaceWith(n),S}),Z(),ie(document))}function oi({location$:e,viewport$:t,progress$:r}){let o=xe();if(location.protocol==="file:")return S;let n=ur(o.base);I(document).subscribe(ri);let i=h(document.body,"click").pipe(He(n),v(([p,c])=>os(p,c)),pe()),a=h(window,"popstate").pipe(m(ye),pe());i.pipe(re(t)).subscribe(([p,{offset:c}])=>{history.replaceState(c,""),history.pushState(null,"",p)}),O(i,a).subscribe(e);let s=e.pipe(ee("pathname"),v(p=>fn(p,{progress$:r}).pipe(de(()=>(lt(p,!0),S)))),v(ri),v(ns),pe());return O(s.pipe(re(e,(p,c)=>c)),s.pipe(v(()=>e),ee("pathname"),v(()=>e),ee("hash")),e.pipe(K((p,c)=>p.pathname===c.pathname&&p.hash===c.hash),v(()=>i),w(()=>history.back()))).subscribe(p=>{var c,l;history.state!==null||!p.hash?window.scrollTo(0,(l=(c=history.state)==null?void 0:c.y)!=null?l:0):(history.scrollRestoration="auto",pn(p.hash),history.scrollRestoration="manual")}),e.subscribe(()=>{history.scrollRestoration="manual"}),h(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}),t.pipe(ee("offset"),_e(100)).subscribe(({offset:p})=>{history.replaceState(p,"")}),s}var ni=Mt(qr());function ii(e){let t=e.separator.split("|").map(n=>n.replace(/(\(\?[!=<][^)]+\))/g,"").length===0?"\uFFFD":n).join("|"),r=new RegExp(t,"img"),o=(n,i,a)=>`${i}${a}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").trim();let i=new RegExp(`(^|${e.separator}|)(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return a=>(0,ni.default)(a).replace(i,o).replace(/<\/mark>(\s+)]*>/img,"$1")}}function jt(e){return e.type===1}function dr(e){return e.type===3}function ai(e,t){let r=yn(e);return O(I(location.protocol!=="file:"),ze("search")).pipe(Ae(o=>o),v(()=>t)).subscribe(({config:o,docs:n})=>r.next({type:0,data:{config:o,docs:n,options:{suggest:B("search.suggest")}}})),r}function si(e){var l;let{selectedVersionSitemap:t,selectedVersionBaseURL:r,currentLocation:o,currentBaseURL:n}=e,i=(l=Xr(n))==null?void 0:l.pathname;if(i===void 0)return;let a=ss(o.pathname,i);if(a===void 0)return;let s=ps(t.keys());if(!t.has(s))return;let p=Xr(a,s);if(!p||!t.has(p.href))return;let c=Xr(a,r);if(c)return c.hash=o.hash,c.search=o.search,c}function Xr(e,t){try{return new URL(e,t)}catch(r){return}}function ss(e,t){if(e.startsWith(t))return e.slice(t.length)}function cs(e,t){let r=Math.min(e.length,t.length),o;for(o=0;oS)),o=r.pipe(m(n=>{let[,i]=t.base.match(/([^/]+)\/?$/);return n.find(({version:a,aliases:s})=>a===i||s.includes(i))||n[0]}));r.pipe(m(n=>new Map(n.map(i=>[`${new URL(`../${i.version}/`,t.base)}`,i]))),v(n=>h(document.body,"click").pipe(b(i=>!i.metaKey&&!i.ctrlKey),re(o),v(([i,a])=>{if(i.target instanceof Element){let s=i.target.closest("a");if(s&&!s.target&&n.has(s.href)){let p=s.href;return!i.target.closest(".md-version")&&n.get(p)===a?S:(i.preventDefault(),I(new URL(p)))}}return S}),v(i=>ur(i).pipe(m(a=>{var s;return(s=si({selectedVersionSitemap:a,selectedVersionBaseURL:i,currentLocation:ye(),currentBaseURL:t.base}))!=null?s:i})))))).subscribe(n=>lt(n,!0)),z([r,o]).subscribe(([n,i])=>{R(".md-header__topic").appendChild(Cn(n,i))}),e.pipe(v(()=>o)).subscribe(n=>{var a;let i=__md_get("__outdated",sessionStorage);if(i===null){i=!0;let s=((a=t.version)==null?void 0:a.default)||"latest";Array.isArray(s)||(s=[s]);e:for(let p of s)for(let c of n.aliases.concat(n.version))if(new RegExp(p,"i").test(c)){i=!1;break e}__md_set("__outdated",i,sessionStorage)}if(i)for(let s of ae("outdated"))s.hidden=!1})}function ls(e,{worker$:t}){let{searchParams:r}=ye();r.has("q")&&(Je("search",!0),e.value=r.get("q"),e.focus(),ze("search").pipe(Ae(i=>!i)).subscribe(()=>{let i=ye();i.searchParams.delete("q"),history.replaceState({},"",`${i}`)}));let o=et(e),n=O(t.pipe(Ae(jt)),h(e,"keyup"),o).pipe(m(()=>e.value),K());return z([n,o]).pipe(m(([i,a])=>({value:i,focus:a})),G(1))}function pi(e,{worker$:t}){let r=new g,o=r.pipe(Z(),ie(!0));z([t.pipe(Ae(jt)),r],(i,a)=>a).pipe(ee("value")).subscribe(({value:i})=>t.next({type:2,data:i})),r.pipe(ee("focus")).subscribe(({focus:i})=>{i&&Je("search",i)}),h(e.form,"reset").pipe(W(o)).subscribe(()=>e.focus());let n=R("header [for=__search]");return h(n,"click").subscribe(()=>e.focus()),ls(e,{worker$:t}).pipe(w(i=>r.next(i)),_(()=>r.complete()),m(i=>$({ref:e},i)),G(1))}function li(e,{worker$:t,query$:r}){let o=new g,n=on(e.parentElement).pipe(b(Boolean)),i=e.parentElement,a=R(":scope > :first-child",e),s=R(":scope > :last-child",e);ze("search").subscribe(l=>s.setAttribute("role",l?"list":"presentation")),o.pipe(re(r),Wr(t.pipe(Ae(jt)))).subscribe(([{items:l},{value:f}])=>{switch(l.length){case 0:a.textContent=f.length?Ee("search.result.none"):Ee("search.result.placeholder");break;case 1:a.textContent=Ee("search.result.one");break;default:let u=sr(l.length);a.textContent=Ee("search.result.other",u)}});let p=o.pipe(w(()=>s.innerHTML=""),v(({items:l})=>O(I(...l.slice(0,10)),I(...l.slice(10)).pipe(Be(4),Vr(n),v(([f])=>f)))),m(Mn),pe());return p.subscribe(l=>s.appendChild(l)),p.pipe(ne(l=>{let f=fe("details",l);return typeof f=="undefined"?S:h(f,"toggle").pipe(W(o),m(()=>f))})).subscribe(l=>{l.open===!1&&l.offsetTop<=i.scrollTop&&i.scrollTo({top:l.offsetTop})}),t.pipe(b(dr),m(({data:l})=>l)).pipe(w(l=>o.next(l)),_(()=>o.complete()),m(l=>$({ref:e},l)))}function ms(e,{query$:t}){return t.pipe(m(({value:r})=>{let o=ye();return o.hash="",r=r.replace(/\s+/g,"+").replace(/&/g,"%26").replace(/=/g,"%3D"),o.search=`q=${r}`,{url:o}}))}function mi(e,t){let r=new g,o=r.pipe(Z(),ie(!0));return r.subscribe(({url:n})=>{e.setAttribute("data-clipboard-text",e.href),e.href=`${n}`}),h(e,"click").pipe(W(o)).subscribe(n=>n.preventDefault()),ms(e,t).pipe(w(n=>r.next(n)),_(()=>r.complete()),m(n=>$({ref:e},n)))}function fi(e,{worker$:t,keyboard$:r}){let o=new g,n=Se("search-query"),i=O(h(n,"keydown"),h(n,"focus")).pipe(ve(se),m(()=>n.value),K());return o.pipe(He(i),m(([{suggest:s},p])=>{let c=p.split(/([\s-]+)/);if(s!=null&&s.length&&c[c.length-1]){let l=s[s.length-1];l.startsWith(c[c.length-1])&&(c[c.length-1]=l)}else c.length=0;return c})).subscribe(s=>e.innerHTML=s.join("").replace(/\s/g," ")),r.pipe(b(({mode:s})=>s==="search")).subscribe(s=>{switch(s.type){case"ArrowRight":e.innerText.length&&n.selectionStart===n.value.length&&(n.value=e.innerText);break}}),t.pipe(b(dr),m(({data:s})=>s)).pipe(w(s=>o.next(s)),_(()=>o.complete()),m(()=>({ref:e})))}function ui(e,{index$:t,keyboard$:r}){let o=xe();try{let n=ai(o.search,t),i=Se("search-query",e),a=Se("search-result",e);h(e,"click").pipe(b(({target:p})=>p instanceof Element&&!!p.closest("a"))).subscribe(()=>Je("search",!1)),r.pipe(b(({mode:p})=>p==="search")).subscribe(p=>{let c=Ie();switch(p.type){case"Enter":if(c===i){let l=new Map;for(let f of P(":first-child [href]",a)){let u=f.firstElementChild;l.set(f,parseFloat(u.getAttribute("data-md-score")))}if(l.size){let[[f]]=[...l].sort(([,u],[,d])=>d-u);f.click()}p.claim()}break;case"Escape":case"Tab":Je("search",!1),i.blur();break;case"ArrowUp":case"ArrowDown":if(typeof c=="undefined")i.focus();else{let l=[i,...P(":not(details) > [href], summary, details[open] [href]",a)],f=Math.max(0,(Math.max(0,l.indexOf(c))+l.length+(p.type==="ArrowUp"?-1:1))%l.length);l[f].focus()}p.claim();break;default:i!==Ie()&&i.focus()}}),r.pipe(b(({mode:p})=>p==="global")).subscribe(p=>{switch(p.type){case"f":case"s":case"/":i.focus(),i.select(),p.claim();break}});let s=pi(i,{worker$:n});return O(s,li(a,{worker$:n,query$:s})).pipe(Re(...ae("search-share",e).map(p=>mi(p,{query$:s})),...ae("search-suggest",e).map(p=>fi(p,{worker$:n,keyboard$:r}))))}catch(n){return e.hidden=!0,Ye}}function di(e,{index$:t,location$:r}){return z([t,r.pipe(Q(ye()),b(o=>!!o.searchParams.get("h")))]).pipe(m(([o,n])=>ii(o.config)(n.searchParams.get("h"))),m(o=>{var a;let n=new Map,i=document.createNodeIterator(e,NodeFilter.SHOW_TEXT);for(let s=i.nextNode();s;s=i.nextNode())if((a=s.parentElement)!=null&&a.offsetHeight){let p=s.textContent,c=o(p);c.length>p.length&&n.set(s,c)}for(let[s,p]of n){let{childNodes:c}=x("span",null,p);s.replaceWith(...Array.from(c))}return{ref:e,nodes:n}}))}function fs(e,{viewport$:t,main$:r}){let o=e.closest(".md-grid"),n=o.offsetTop-o.parentElement.offsetTop;return z([r,t]).pipe(m(([{offset:i,height:a},{offset:{y:s}}])=>(a=a+Math.min(n,Math.max(0,s-i))-n,{height:a,locked:s>=i+n})),K((i,a)=>i.height===a.height&&i.locked===a.locked))}function Zr(e,o){var n=o,{header$:t}=n,r=so(n,["header$"]);let i=R(".md-sidebar__scrollwrap",e),{y:a}=Ve(i);return C(()=>{let s=new g,p=s.pipe(Z(),ie(!0)),c=s.pipe(Me(0,me));return c.pipe(re(t)).subscribe({next([{height:l},{height:f}]){i.style.height=`${l-2*a}px`,e.style.top=`${f}px`},complete(){i.style.height="",e.style.top=""}}),c.pipe(Ae()).subscribe(()=>{for(let l of P(".md-nav__link--active[href]",e)){if(!l.clientHeight)continue;let f=l.closest(".md-sidebar__scrollwrap");if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=ce(f);f.scrollTo({top:u-d/2})}}}),ue(P("label[tabindex]",e)).pipe(ne(l=>h(l,"click").pipe(ve(se),m(()=>l),W(p)))).subscribe(l=>{let f=R(`[id="${l.htmlFor}"]`);R(`[aria-labelledby="${l.id}"]`).setAttribute("aria-expanded",`${f.checked}`)}),fs(e,r).pipe(w(l=>s.next(l)),_(()=>s.complete()),m(l=>$({ref:e},l)))})}function hi(e,t){if(typeof t!="undefined"){let r=`https://api.github.com/repos/${e}/${t}`;return st(je(`${r}/releases/latest`).pipe(de(()=>S),m(o=>({version:o.tag_name})),De({})),je(r).pipe(de(()=>S),m(o=>({stars:o.stargazers_count,forks:o.forks_count})),De({}))).pipe(m(([o,n])=>$($({},o),n)))}else{let r=`https://api.github.com/users/${e}`;return je(r).pipe(m(o=>({repositories:o.public_repos})),De({}))}}function bi(e,t){let r=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return st(je(`${r}/releases/permalink/latest`).pipe(de(()=>S),m(({tag_name:o})=>({version:o})),De({})),je(r).pipe(de(()=>S),m(({star_count:o,forks_count:n})=>({stars:o,forks:n})),De({}))).pipe(m(([o,n])=>$($({},o),n)))}function vi(e){let t=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);if(t){let[,r,o]=t;return hi(r,o)}if(t=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i),t){let[,r,o]=t;return bi(r,o)}return S}var us;function ds(e){return us||(us=C(()=>{let t=__md_get("__source",sessionStorage);if(t)return I(t);if(ae("consent").length){let o=__md_get("__consent");if(!(o&&o.github))return S}return vi(e.href).pipe(w(o=>__md_set("__source",o,sessionStorage)))}).pipe(de(()=>S),b(t=>Object.keys(t).length>0),m(t=>({facts:t})),G(1)))}function gi(e){let t=R(":scope > :last-child",e);return C(()=>{let r=new g;return r.subscribe(({facts:o})=>{t.appendChild(_n(o)),t.classList.add("md-source__repository--active")}),ds(e).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}function hs(e,{viewport$:t,header$:r}){return ge(document.body).pipe(v(()=>mr(e,{header$:r,viewport$:t})),m(({offset:{y:o}})=>({hidden:o>=10})),ee("hidden"))}function yi(e,t){return C(()=>{let r=new g;return r.subscribe({next({hidden:o}){e.hidden=o},complete(){e.hidden=!1}}),(B("navigation.tabs.sticky")?I({hidden:!1}):hs(e,t)).pipe(w(o=>r.next(o)),_(()=>r.complete()),m(o=>$({ref:e},o)))})}function bs(e,{viewport$:t,header$:r}){let o=new Map,n=P(".md-nav__link",e);for(let s of n){let p=decodeURIComponent(s.hash.substring(1)),c=fe(`[id="${p}"]`);typeof c!="undefined"&&o.set(s,c)}let i=r.pipe(ee("height"),m(({height:s})=>{let p=Se("main"),c=R(":scope > :first-child",p);return s+.8*(c.offsetTop-p.offsetTop)}),pe());return ge(document.body).pipe(ee("height"),v(s=>C(()=>{let p=[];return I([...o].reduce((c,[l,f])=>{for(;p.length&&o.get(p[p.length-1]).tagName>=f.tagName;)p.pop();let u=f.offsetTop;for(;!u&&f.parentElement;)f=f.parentElement,u=f.offsetTop;let d=f.offsetParent;for(;d;d=d.offsetParent)u+=d.offsetTop;return c.set([...p=[...p,l]].reverse(),u)},new Map))}).pipe(m(p=>new Map([...p].sort(([,c],[,l])=>c-l))),He(i),v(([p,c])=>t.pipe(Fr(([l,f],{offset:{y:u},size:d})=>{let y=u+d.height>=Math.floor(s.height);for(;f.length;){let[,L]=f[0];if(L-c=u&&!y)f=[l.pop(),...f];else break}return[l,f]},[[],[...p]]),K((l,f)=>l[0]===f[0]&&l[1]===f[1])))))).pipe(m(([s,p])=>({prev:s.map(([c])=>c),next:p.map(([c])=>c)})),Q({prev:[],next:[]}),Be(2,1),m(([s,p])=>s.prev.length{let i=new g,a=i.pipe(Z(),ie(!0));if(i.subscribe(({prev:s,next:p})=>{for(let[c]of p)c.classList.remove("md-nav__link--passed"),c.classList.remove("md-nav__link--active");for(let[c,[l]]of s.entries())l.classList.add("md-nav__link--passed"),l.classList.toggle("md-nav__link--active",c===s.length-1)}),B("toc.follow")){let s=O(t.pipe(_e(1),m(()=>{})),t.pipe(_e(250),m(()=>"smooth")));i.pipe(b(({prev:p})=>p.length>0),He(o.pipe(ve(se))),re(s)).subscribe(([[{prev:p}],c])=>{let[l]=p[p.length-1];if(l.offsetHeight){let f=cr(l);if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:d}=ce(f);f.scrollTo({top:u-d/2,behavior:c})}}})}return B("navigation.tracking")&&t.pipe(W(a),ee("offset"),_e(250),Ce(1),W(n.pipe(Ce(1))),ct({delay:250}),re(i)).subscribe(([,{prev:s}])=>{let p=ye(),c=s[s.length-1];if(c&&c.length){let[l]=c,{hash:f}=new URL(l.href);p.hash!==f&&(p.hash=f,history.replaceState({},"",`${p}`))}else p.hash="",history.replaceState({},"",`${p}`)}),bs(e,{viewport$:t,header$:r}).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))})}function vs(e,{viewport$:t,main$:r,target$:o}){let n=t.pipe(m(({offset:{y:a}})=>a),Be(2,1),m(([a,s])=>a>s&&s>0),K()),i=r.pipe(m(({active:a})=>a));return z([i,n]).pipe(m(([a,s])=>!(a&&s)),K(),W(o.pipe(Ce(1))),ie(!0),ct({delay:250}),m(a=>({hidden:a})))}function Ei(e,{viewport$:t,header$:r,main$:o,target$:n}){let i=new g,a=i.pipe(Z(),ie(!0));return i.subscribe({next({hidden:s}){e.hidden=s,s?(e.setAttribute("tabindex","-1"),e.blur()):e.removeAttribute("tabindex")},complete(){e.style.top="",e.hidden=!0,e.removeAttribute("tabindex")}}),r.pipe(W(a),ee("height")).subscribe(({height:s})=>{e.style.top=`${s+16}px`}),h(e,"click").subscribe(s=>{s.preventDefault(),window.scrollTo({top:0})}),vs(e,{viewport$:t,main$:o,target$:n}).pipe(w(s=>i.next(s)),_(()=>i.complete()),m(s=>$({ref:e},s)))}function wi({document$:e,viewport$:t}){e.pipe(v(()=>P(".md-ellipsis")),ne(r=>tt(r).pipe(W(e.pipe(Ce(1))),b(o=>o),m(()=>r),Te(1))),b(r=>r.offsetWidth{let o=r.innerText,n=r.closest("a")||r;return n.title=o,B("content.tooltips")?mt(n,{viewport$:t}).pipe(W(e.pipe(Ce(1))),_(()=>n.removeAttribute("title"))):S})).subscribe(),B("content.tooltips")&&e.pipe(v(()=>P(".md-status")),ne(r=>mt(r,{viewport$:t}))).subscribe()}function Ti({document$:e,tablet$:t}){e.pipe(v(()=>P(".md-toggle--indeterminate")),w(r=>{r.indeterminate=!0,r.checked=!1}),ne(r=>h(r,"change").pipe(Dr(()=>r.classList.contains("md-toggle--indeterminate")),m(()=>r))),re(t)).subscribe(([r,o])=>{r.classList.remove("md-toggle--indeterminate"),o&&(r.checked=!1)})}function gs(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}function Si({document$:e}){e.pipe(v(()=>P("[data-md-scrollfix]")),w(t=>t.removeAttribute("data-md-scrollfix")),b(gs),ne(t=>h(t,"touchstart").pipe(m(()=>t)))).subscribe(t=>{let r=t.scrollTop;r===0?t.scrollTop=1:r+t.offsetHeight===t.scrollHeight&&(t.scrollTop=r-1)})}function Oi({viewport$:e,tablet$:t}){z([ze("search"),t]).pipe(m(([r,o])=>r&&!o),v(r=>I(r).pipe(Ge(r?400:100))),re(e)).subscribe(([r,{offset:{y:o}}])=>{if(r)document.body.setAttribute("data-md-scrolllock",""),document.body.style.top=`-${o}px`;else{let n=-1*parseInt(document.body.style.top,10);document.body.removeAttribute("data-md-scrolllock"),document.body.style.top="",n&&window.scrollTo(0,n)}})}Object.entries||(Object.entries=function(e){let t=[];for(let r of Object.keys(e))t.push([r,e[r]]);return t});Object.values||(Object.values=function(e){let t=[];for(let r of Object.keys(e))t.push(e[r]);return t});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(e,t){typeof e=="object"?(this.scrollLeft=e.left,this.scrollTop=e.top):(this.scrollLeft=e,this.scrollTop=t)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...e){let t=this.parentNode;if(t){e.length===0&&t.removeChild(this);for(let r=e.length-1;r>=0;r--){let o=e[r];typeof o=="string"?o=document.createTextNode(o):o.parentNode&&o.parentNode.removeChild(o),r?t.insertBefore(this.previousSibling,o):t.replaceChild(o,this)}}}));function ys(){return location.protocol==="file:"?Tt(`${new URL("search/search_index.js",eo.base)}`).pipe(m(()=>__index),G(1)):je(new URL("search/search_index.json",eo.base))}document.documentElement.classList.remove("no-js");document.documentElement.classList.add("js");var ot=Go(),Ut=sn(),Lt=ln(Ut),to=an(),Oe=gn(),hr=Pt("(min-width: 960px)"),Mi=Pt("(min-width: 1220px)"),_i=mn(),eo=xe(),Ai=document.forms.namedItem("search")?ys():Ye,ro=new g;Zn({alert$:ro});var oo=new g;B("navigation.instant")&&oi({location$:Ut,viewport$:Oe,progress$:oo}).subscribe(ot);var Li;((Li=eo.version)==null?void 0:Li.provider)==="mike"&&ci({document$:ot});O(Ut,Lt).pipe(Ge(125)).subscribe(()=>{Je("drawer",!1),Je("search",!1)});to.pipe(b(({mode:e})=>e==="global")).subscribe(e=>{switch(e.type){case"p":case",":let t=fe("link[rel=prev]");typeof t!="undefined"&<(t);break;case"n":case".":let r=fe("link[rel=next]");typeof r!="undefined"&<(r);break;case"Enter":let o=Ie();o instanceof HTMLLabelElement&&o.click()}});wi({viewport$:Oe,document$:ot});Ti({document$:ot,tablet$:hr});Si({document$:ot});Oi({viewport$:Oe,tablet$:hr});var rt=Kn(Se("header"),{viewport$:Oe}),Ft=ot.pipe(m(()=>Se("main")),v(e=>Gn(e,{viewport$:Oe,header$:rt})),G(1)),xs=O(...ae("consent").map(e=>En(e,{target$:Lt})),...ae("dialog").map(e=>qn(e,{alert$:ro})),...ae("palette").map(e=>Jn(e)),...ae("progress").map(e=>Xn(e,{progress$:oo})),...ae("search").map(e=>ui(e,{index$:Ai,keyboard$:to})),...ae("source").map(e=>gi(e))),Es=C(()=>O(...ae("announce").map(e=>xn(e)),...ae("content").map(e=>zn(e,{viewport$:Oe,target$:Lt,print$:_i})),...ae("content").map(e=>B("search.highlight")?di(e,{index$:Ai,location$:Ut}):S),...ae("header").map(e=>Yn(e,{viewport$:Oe,header$:rt,main$:Ft})),...ae("header-title").map(e=>Bn(e,{viewport$:Oe,header$:rt})),...ae("sidebar").map(e=>e.getAttribute("data-md-type")==="navigation"?Nr(Mi,()=>Zr(e,{viewport$:Oe,header$:rt,main$:Ft})):Nr(hr,()=>Zr(e,{viewport$:Oe,header$:rt,main$:Ft}))),...ae("tabs").map(e=>yi(e,{viewport$:Oe,header$:rt})),...ae("toc").map(e=>xi(e,{viewport$:Oe,header$:rt,main$:Ft,target$:Lt})),...ae("top").map(e=>Ei(e,{viewport$:Oe,header$:rt,main$:Ft,target$:Lt})))),Ci=ot.pipe(v(()=>Es),Re(xs),G(1));Ci.subscribe();window.document$=ot;window.location$=Ut;window.target$=Lt;window.keyboard$=to;window.viewport$=Oe;window.tablet$=hr;window.screen$=Mi;window.print$=_i;window.alert$=ro;window.progress$=oo;window.component$=Ci;})(); +//# sourceMappingURL=bundle.88dd0f4e.min.js.map + diff --git a/assets/javascripts/bundle.88dd0f4e.min.js.map b/assets/javascripts/bundle.88dd0f4e.min.js.map new file mode 100644 index 000000000..dab2a8754 --- /dev/null +++ b/assets/javascripts/bundle.88dd0f4e.min.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["node_modules/focus-visible/dist/focus-visible.js", "node_modules/escape-html/index.js", "node_modules/clipboard/dist/clipboard.js", "src/templates/assets/javascripts/bundle.ts", "node_modules/tslib/tslib.es6.mjs", "node_modules/rxjs/src/internal/util/isFunction.ts", "node_modules/rxjs/src/internal/util/createErrorClass.ts", "node_modules/rxjs/src/internal/util/UnsubscriptionError.ts", "node_modules/rxjs/src/internal/util/arrRemove.ts", "node_modules/rxjs/src/internal/Subscription.ts", "node_modules/rxjs/src/internal/config.ts", "node_modules/rxjs/src/internal/scheduler/timeoutProvider.ts", "node_modules/rxjs/src/internal/util/reportUnhandledError.ts", "node_modules/rxjs/src/internal/util/noop.ts", "node_modules/rxjs/src/internal/NotificationFactories.ts", "node_modules/rxjs/src/internal/util/errorContext.ts", "node_modules/rxjs/src/internal/Subscriber.ts", "node_modules/rxjs/src/internal/symbol/observable.ts", "node_modules/rxjs/src/internal/util/identity.ts", "node_modules/rxjs/src/internal/util/pipe.ts", "node_modules/rxjs/src/internal/Observable.ts", "node_modules/rxjs/src/internal/util/lift.ts", "node_modules/rxjs/src/internal/operators/OperatorSubscriber.ts", "node_modules/rxjs/src/internal/scheduler/animationFrameProvider.ts", "node_modules/rxjs/src/internal/util/ObjectUnsubscribedError.ts", "node_modules/rxjs/src/internal/Subject.ts", "node_modules/rxjs/src/internal/BehaviorSubject.ts", "node_modules/rxjs/src/internal/scheduler/dateTimestampProvider.ts", "node_modules/rxjs/src/internal/ReplaySubject.ts", "node_modules/rxjs/src/internal/scheduler/Action.ts", "node_modules/rxjs/src/internal/scheduler/intervalProvider.ts", "node_modules/rxjs/src/internal/scheduler/AsyncAction.ts", "node_modules/rxjs/src/internal/Scheduler.ts", "node_modules/rxjs/src/internal/scheduler/AsyncScheduler.ts", "node_modules/rxjs/src/internal/scheduler/async.ts", "node_modules/rxjs/src/internal/scheduler/QueueAction.ts", "node_modules/rxjs/src/internal/scheduler/QueueScheduler.ts", "node_modules/rxjs/src/internal/scheduler/queue.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameAction.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameScheduler.ts", "node_modules/rxjs/src/internal/scheduler/animationFrame.ts", "node_modules/rxjs/src/internal/observable/empty.ts", "node_modules/rxjs/src/internal/util/isScheduler.ts", "node_modules/rxjs/src/internal/util/args.ts", "node_modules/rxjs/src/internal/util/isArrayLike.ts", "node_modules/rxjs/src/internal/util/isPromise.ts", "node_modules/rxjs/src/internal/util/isInteropObservable.ts", "node_modules/rxjs/src/internal/util/isAsyncIterable.ts", "node_modules/rxjs/src/internal/util/throwUnobservableError.ts", "node_modules/rxjs/src/internal/symbol/iterator.ts", "node_modules/rxjs/src/internal/util/isIterable.ts", "node_modules/rxjs/src/internal/util/isReadableStreamLike.ts", "node_modules/rxjs/src/internal/observable/innerFrom.ts", "node_modules/rxjs/src/internal/util/executeSchedule.ts", "node_modules/rxjs/src/internal/operators/observeOn.ts", "node_modules/rxjs/src/internal/operators/subscribeOn.ts", "node_modules/rxjs/src/internal/scheduled/scheduleObservable.ts", "node_modules/rxjs/src/internal/scheduled/schedulePromise.ts", "node_modules/rxjs/src/internal/scheduled/scheduleArray.ts", "node_modules/rxjs/src/internal/scheduled/scheduleIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleAsyncIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleReadableStreamLike.ts", "node_modules/rxjs/src/internal/scheduled/scheduled.ts", "node_modules/rxjs/src/internal/observable/from.ts", "node_modules/rxjs/src/internal/observable/of.ts", "node_modules/rxjs/src/internal/observable/throwError.ts", "node_modules/rxjs/src/internal/util/EmptyError.ts", "node_modules/rxjs/src/internal/util/isDate.ts", "node_modules/rxjs/src/internal/operators/map.ts", "node_modules/rxjs/src/internal/util/mapOneOrManyArgs.ts", "node_modules/rxjs/src/internal/util/argsArgArrayOrObject.ts", "node_modules/rxjs/src/internal/util/createObject.ts", "node_modules/rxjs/src/internal/observable/combineLatest.ts", "node_modules/rxjs/src/internal/operators/mergeInternals.ts", "node_modules/rxjs/src/internal/operators/mergeMap.ts", "node_modules/rxjs/src/internal/operators/mergeAll.ts", "node_modules/rxjs/src/internal/operators/concatAll.ts", "node_modules/rxjs/src/internal/observable/concat.ts", "node_modules/rxjs/src/internal/observable/defer.ts", "node_modules/rxjs/src/internal/observable/fromEvent.ts", "node_modules/rxjs/src/internal/observable/fromEventPattern.ts", "node_modules/rxjs/src/internal/observable/timer.ts", "node_modules/rxjs/src/internal/observable/merge.ts", "node_modules/rxjs/src/internal/observable/never.ts", "node_modules/rxjs/src/internal/util/argsOrArgArray.ts", "node_modules/rxjs/src/internal/operators/filter.ts", "node_modules/rxjs/src/internal/observable/zip.ts", "node_modules/rxjs/src/internal/operators/audit.ts", "node_modules/rxjs/src/internal/operators/auditTime.ts", "node_modules/rxjs/src/internal/operators/bufferCount.ts", "node_modules/rxjs/src/internal/operators/catchError.ts", "node_modules/rxjs/src/internal/operators/scanInternals.ts", "node_modules/rxjs/src/internal/operators/combineLatest.ts", "node_modules/rxjs/src/internal/operators/combineLatestWith.ts", "node_modules/rxjs/src/internal/operators/debounce.ts", "node_modules/rxjs/src/internal/operators/debounceTime.ts", "node_modules/rxjs/src/internal/operators/defaultIfEmpty.ts", "node_modules/rxjs/src/internal/operators/take.ts", "node_modules/rxjs/src/internal/operators/ignoreElements.ts", "node_modules/rxjs/src/internal/operators/mapTo.ts", "node_modules/rxjs/src/internal/operators/delayWhen.ts", "node_modules/rxjs/src/internal/operators/delay.ts", "node_modules/rxjs/src/internal/operators/distinctUntilChanged.ts", "node_modules/rxjs/src/internal/operators/distinctUntilKeyChanged.ts", "node_modules/rxjs/src/internal/operators/throwIfEmpty.ts", "node_modules/rxjs/src/internal/operators/endWith.ts", "node_modules/rxjs/src/internal/operators/finalize.ts", "node_modules/rxjs/src/internal/operators/first.ts", "node_modules/rxjs/src/internal/operators/takeLast.ts", "node_modules/rxjs/src/internal/operators/merge.ts", "node_modules/rxjs/src/internal/operators/mergeWith.ts", "node_modules/rxjs/src/internal/operators/repeat.ts", "node_modules/rxjs/src/internal/operators/scan.ts", "node_modules/rxjs/src/internal/operators/share.ts", "node_modules/rxjs/src/internal/operators/shareReplay.ts", "node_modules/rxjs/src/internal/operators/skip.ts", "node_modules/rxjs/src/internal/operators/skipUntil.ts", "node_modules/rxjs/src/internal/operators/startWith.ts", "node_modules/rxjs/src/internal/operators/switchMap.ts", "node_modules/rxjs/src/internal/operators/takeUntil.ts", "node_modules/rxjs/src/internal/operators/takeWhile.ts", "node_modules/rxjs/src/internal/operators/tap.ts", "node_modules/rxjs/src/internal/operators/throttle.ts", "node_modules/rxjs/src/internal/operators/throttleTime.ts", "node_modules/rxjs/src/internal/operators/withLatestFrom.ts", "node_modules/rxjs/src/internal/operators/zip.ts", "node_modules/rxjs/src/internal/operators/zipWith.ts", "src/templates/assets/javascripts/browser/document/index.ts", "src/templates/assets/javascripts/browser/element/_/index.ts", "src/templates/assets/javascripts/browser/element/focus/index.ts", "src/templates/assets/javascripts/browser/element/hover/index.ts", "src/templates/assets/javascripts/utilities/h/index.ts", "src/templates/assets/javascripts/utilities/round/index.ts", "src/templates/assets/javascripts/browser/script/index.ts", "src/templates/assets/javascripts/browser/element/size/_/index.ts", "src/templates/assets/javascripts/browser/element/size/content/index.ts", "src/templates/assets/javascripts/browser/element/offset/_/index.ts", "src/templates/assets/javascripts/browser/element/offset/content/index.ts", "src/templates/assets/javascripts/browser/element/visibility/index.ts", "src/templates/assets/javascripts/browser/toggle/index.ts", "src/templates/assets/javascripts/browser/keyboard/index.ts", "src/templates/assets/javascripts/browser/location/_/index.ts", "src/templates/assets/javascripts/browser/location/hash/index.ts", "src/templates/assets/javascripts/browser/media/index.ts", "src/templates/assets/javascripts/browser/request/index.ts", "src/templates/assets/javascripts/browser/viewport/offset/index.ts", "src/templates/assets/javascripts/browser/viewport/size/index.ts", "src/templates/assets/javascripts/browser/viewport/_/index.ts", "src/templates/assets/javascripts/browser/viewport/at/index.ts", "src/templates/assets/javascripts/browser/worker/index.ts", "src/templates/assets/javascripts/_/index.ts", "src/templates/assets/javascripts/components/_/index.ts", "src/templates/assets/javascripts/components/announce/index.ts", "src/templates/assets/javascripts/components/consent/index.ts", "src/templates/assets/javascripts/templates/tooltip/index.tsx", "src/templates/assets/javascripts/templates/annotation/index.tsx", "src/templates/assets/javascripts/templates/clipboard/index.tsx", "src/templates/assets/javascripts/templates/search/index.tsx", "src/templates/assets/javascripts/templates/source/index.tsx", "src/templates/assets/javascripts/templates/tabbed/index.tsx", "src/templates/assets/javascripts/templates/table/index.tsx", "src/templates/assets/javascripts/templates/version/index.tsx", "src/templates/assets/javascripts/components/tooltip2/index.ts", "src/templates/assets/javascripts/components/content/annotation/_/index.ts", "src/templates/assets/javascripts/components/content/annotation/list/index.ts", "src/templates/assets/javascripts/components/content/annotation/block/index.ts", "src/templates/assets/javascripts/components/content/code/_/index.ts", "src/templates/assets/javascripts/components/content/details/index.ts", "src/templates/assets/javascripts/components/content/mermaid/index.css", "src/templates/assets/javascripts/components/content/mermaid/index.ts", "src/templates/assets/javascripts/components/content/table/index.ts", "src/templates/assets/javascripts/components/content/tabs/index.ts", "src/templates/assets/javascripts/components/content/_/index.ts", "src/templates/assets/javascripts/components/dialog/index.ts", "src/templates/assets/javascripts/components/tooltip/index.ts", "src/templates/assets/javascripts/components/header/_/index.ts", "src/templates/assets/javascripts/components/header/title/index.ts", "src/templates/assets/javascripts/components/main/index.ts", "src/templates/assets/javascripts/components/palette/index.ts", "src/templates/assets/javascripts/components/progress/index.ts", "src/templates/assets/javascripts/integrations/clipboard/index.ts", "src/templates/assets/javascripts/integrations/sitemap/index.ts", "src/templates/assets/javascripts/integrations/instant/index.ts", "src/templates/assets/javascripts/integrations/search/highlighter/index.ts", "src/templates/assets/javascripts/integrations/search/worker/message/index.ts", "src/templates/assets/javascripts/integrations/search/worker/_/index.ts", "src/templates/assets/javascripts/integrations/version/findurl/index.ts", "src/templates/assets/javascripts/integrations/version/index.ts", "src/templates/assets/javascripts/components/search/query/index.ts", "src/templates/assets/javascripts/components/search/result/index.ts", "src/templates/assets/javascripts/components/search/share/index.ts", "src/templates/assets/javascripts/components/search/suggest/index.ts", "src/templates/assets/javascripts/components/search/_/index.ts", "src/templates/assets/javascripts/components/search/highlight/index.ts", "src/templates/assets/javascripts/components/sidebar/index.ts", "src/templates/assets/javascripts/components/source/facts/github/index.ts", "src/templates/assets/javascripts/components/source/facts/gitlab/index.ts", "src/templates/assets/javascripts/components/source/facts/_/index.ts", "src/templates/assets/javascripts/components/source/_/index.ts", "src/templates/assets/javascripts/components/tabs/index.ts", "src/templates/assets/javascripts/components/toc/index.ts", "src/templates/assets/javascripts/components/top/index.ts", "src/templates/assets/javascripts/patches/ellipsis/index.ts", "src/templates/assets/javascripts/patches/indeterminate/index.ts", "src/templates/assets/javascripts/patches/scrollfix/index.ts", "src/templates/assets/javascripts/patches/scrolllock/index.ts", "src/templates/assets/javascripts/polyfills/index.ts"], + "sourcesContent": ["(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. \u00AF\\_(\u30C4)_/\u00AF\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n", "/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n", "/*!\n * clipboard.js v2.0.11\n * https://clipboardjs.com/\n *\n * Licensed MIT \u00A9 Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function() { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 686:\n/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"default\": function() { return /* binding */ clipboard; }\n});\n\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(279);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(370);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(817);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n;// CONCATENATED MODULE: ./src/common/command.js\n/**\n * Executes a given operation type.\n * @param {String} type\n * @return {Boolean}\n */\nfunction command(type) {\n try {\n return document.execCommand(type);\n } catch (err) {\n return false;\n }\n}\n;// CONCATENATED MODULE: ./src/actions/cut.js\n\n\n/**\n * Cut action wrapper.\n * @param {String|HTMLElement} target\n * @return {String}\n */\n\nvar ClipboardActionCut = function ClipboardActionCut(target) {\n var selectedText = select_default()(target);\n command('cut');\n return selectedText;\n};\n\n/* harmony default export */ var actions_cut = (ClipboardActionCut);\n;// CONCATENATED MODULE: ./src/common/create-fake-element.js\n/**\n * Creates a fake textarea element with a value.\n * @param {String} value\n * @return {HTMLElement}\n */\nfunction createFakeElement(value) {\n var isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS\n\n fakeElement.style.fontSize = '12pt'; // Reset box model\n\n fakeElement.style.border = '0';\n fakeElement.style.padding = '0';\n fakeElement.style.margin = '0'; // Move element out of screen horizontally\n\n fakeElement.style.position = 'absolute';\n fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically\n\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n fakeElement.style.top = \"\".concat(yPosition, \"px\");\n fakeElement.setAttribute('readonly', '');\n fakeElement.value = value;\n return fakeElement;\n}\n;// CONCATENATED MODULE: ./src/actions/copy.js\n\n\n\n/**\n * Create fake copy action wrapper using a fake element.\n * @param {String} target\n * @param {Object} options\n * @return {String}\n */\n\nvar fakeCopyAction = function fakeCopyAction(value, options) {\n var fakeElement = createFakeElement(value);\n options.container.appendChild(fakeElement);\n var selectedText = select_default()(fakeElement);\n command('copy');\n fakeElement.remove();\n return selectedText;\n};\n/**\n * Copy action wrapper.\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @return {String}\n */\n\n\nvar ClipboardActionCopy = function ClipboardActionCopy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n var selectedText = '';\n\n if (typeof target === 'string') {\n selectedText = fakeCopyAction(target, options);\n } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {\n // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n selectedText = fakeCopyAction(target.value, options);\n } else {\n selectedText = select_default()(target);\n command('copy');\n }\n\n return selectedText;\n};\n\n/* harmony default export */ var actions_copy = (ClipboardActionCopy);\n;// CONCATENATED MODULE: ./src/actions/default.js\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n\n\n/**\n * Inner function which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n * @param {Object} options\n */\n\nvar ClipboardActionDefault = function ClipboardActionDefault() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Defines base properties passed from constructor.\n var _options$action = options.action,\n action = _options$action === void 0 ? 'copy' : _options$action,\n container = options.container,\n target = options.target,\n text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.\n\n if (action !== 'copy' && action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n } // Sets the `target` property using an element that will be have its content copied.\n\n\n if (target !== undefined) {\n if (target && _typeof(target) === 'object' && target.nodeType === 1) {\n if (action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n } // Define selection strategy based on `text` property.\n\n\n if (text) {\n return actions_copy(text, {\n container: container\n });\n } // Defines which selection strategy based on `target` property.\n\n\n if (target) {\n return action === 'cut' ? actions_cut(target) : actions_copy(target, {\n container: container\n });\n }\n};\n\n/* harmony default export */ var actions_default = (ClipboardActionDefault);\n;// CONCATENATED MODULE: ./src/clipboard.js\nfunction clipboard_typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return clipboard_typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\nfunction getAttributeValue(suffix, element) {\n var attribute = \"data-clipboard-\".concat(suffix);\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\n\nvar Clipboard = /*#__PURE__*/function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n var _super = _createSuper(Clipboard);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n var _this;\n\n _classCallCheck(this, Clipboard);\n\n _this = _super.call(this);\n\n _this.resolveOptions(options);\n\n _this.listenClick(trigger);\n\n return _this;\n }\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: \"resolveOptions\",\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: \"listenClick\",\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: \"onClick\",\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n var action = this.action(trigger) || 'copy';\n var text = actions_default({\n action: action,\n container: this.container,\n target: this.target(trigger),\n text: this.text(trigger)\n }); // Fires an event based on the copy operation result.\n\n this.emit(text ? 'success' : 'error', {\n action: action,\n text: text,\n trigger: trigger,\n clearSelection: function clearSelection() {\n if (trigger) {\n trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n });\n }\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultAction\",\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultTarget\",\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n /**\n * Allow fire programmatically a copy action\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @returns Text copied.\n */\n\n }, {\n key: \"defaultText\",\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: \"destroy\",\n value: function destroy() {\n this.listener.destroy();\n }\n }], [{\n key: \"copy\",\n value: function copy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n return actions_copy(target, options);\n }\n /**\n * Allow fire programmatically a cut action\n * @param {String|HTMLElement} target\n * @returns Text cutted.\n */\n\n }, {\n key: \"cut\",\n value: function cut(target) {\n return actions_cut(target);\n }\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: \"isSupported\",\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n return support;\n }\n }]);\n\n return Clipboard;\n}((tiny_emitter_default()));\n\n/* harmony default export */ var clipboard = (Clipboard);\n\n/***/ }),\n\n/***/ 828:\n/***/ (function(module) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n\n/***/ 438:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar closest = __webpack_require__(828);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n\n/***/ 879:\n/***/ (function(__unused_webpack_module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n\n/***/ 370:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar is = __webpack_require__(879);\nvar delegate = __webpack_require__(438);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n\n/***/ 817:\n/***/ (function(module) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n\n/***/ 279:\n/***/ (function(module) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(__webpack_module_cache__[moduleId]) {\n/******/ \t\t\treturn __webpack_module_cache__[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t!function() {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = function(module) {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\tfunction() { return module['default']; } :\n/******/ \t\t\t\tfunction() { return module; };\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t!function() {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = function(exports, definition) {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t!function() {\n/******/ \t\t__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }\n/******/ \t}();\n/******/ \t\n/************************************************************************/\n/******/ \t// module exports must be returned from runtime so entry inlining is disabled\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(686);\n/******/ })()\n.default;\n});", "/*\n * Copyright (c) 2016-2024 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"focus-visible\"\n\nimport {\n EMPTY,\n NEVER,\n Observable,\n Subject,\n defer,\n delay,\n filter,\n map,\n merge,\n mergeWith,\n shareReplay,\n switchMap\n} from \"rxjs\"\n\nimport { configuration, feature } from \"./_\"\nimport {\n at,\n getActiveElement,\n getOptionalElement,\n requestJSON,\n setLocation,\n setToggle,\n watchDocument,\n watchKeyboard,\n watchLocation,\n watchLocationTarget,\n watchMedia,\n watchPrint,\n watchScript,\n watchViewport\n} from \"./browser\"\nimport {\n getComponentElement,\n getComponentElements,\n mountAnnounce,\n mountBackToTop,\n mountConsent,\n mountContent,\n mountDialog,\n mountHeader,\n mountHeaderTitle,\n mountPalette,\n mountProgress,\n mountSearch,\n mountSearchHiglight,\n mountSidebar,\n mountSource,\n mountTableOfContents,\n mountTabs,\n watchHeader,\n watchMain\n} from \"./components\"\nimport {\n SearchIndex,\n setupClipboardJS,\n setupInstantNavigation,\n setupVersionSelector\n} from \"./integrations\"\nimport {\n patchEllipsis,\n patchIndeterminate,\n patchScrollfix,\n patchScrolllock\n} from \"./patches\"\nimport \"./polyfills\"\n\n/* ----------------------------------------------------------------------------\n * Functions - @todo refactor\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch search index\n *\n * @returns Search index observable\n */\nfunction fetchSearchIndex(): Observable {\n if (location.protocol === \"file:\") {\n return watchScript(\n `${new URL(\"search/search_index.js\", config.base)}`\n )\n .pipe(\n // @ts-ignore - @todo fix typings\n map(() => __index),\n shareReplay(1)\n )\n } else {\n return requestJSON(\n new URL(\"search/search_index.json\", config.base)\n )\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Application\n * ------------------------------------------------------------------------- */\n\n/* Yay, JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Set up navigation observables and subjects */\nconst document$ = watchDocument()\nconst location$ = watchLocation()\nconst target$ = watchLocationTarget(location$)\nconst keyboard$ = watchKeyboard()\n\n/* Set up media observables */\nconst viewport$ = watchViewport()\nconst tablet$ = watchMedia(\"(min-width: 960px)\")\nconst screen$ = watchMedia(\"(min-width: 1220px)\")\nconst print$ = watchPrint()\n\n/* Retrieve search index, if search is enabled */\nconst config = configuration()\nconst index$ = document.forms.namedItem(\"search\")\n ? fetchSearchIndex()\n : NEVER\n\n/* Set up Clipboard.js integration */\nconst alert$ = new Subject()\nsetupClipboardJS({ alert$ })\n\n/* Set up progress indicator */\nconst progress$ = new Subject()\n\n/* Set up instant navigation, if enabled */\nif (feature(\"navigation.instant\"))\n setupInstantNavigation({ location$, viewport$, progress$ })\n .subscribe(document$)\n\n/* Set up version selector */\nif (config.version?.provider === \"mike\")\n setupVersionSelector({ document$ })\n\n/* Always close drawer and search on navigation */\nmerge(location$, target$)\n .pipe(\n delay(125)\n )\n .subscribe(() => {\n setToggle(\"drawer\", false)\n setToggle(\"search\", false)\n })\n\n/* Set up global keyboard handlers */\nkeyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\")\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getOptionalElement(\"link[rel=prev]\")\n if (typeof prev !== \"undefined\")\n setLocation(prev)\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getOptionalElement(\"link[rel=next]\")\n if (typeof next !== \"undefined\")\n setLocation(next)\n break\n\n /* Expand navigation, see https://bit.ly/3ZjG5io */\n case \"Enter\":\n const active = getActiveElement()\n if (active instanceof HTMLLabelElement)\n active.click()\n }\n })\n\n/* Set up patches */\npatchEllipsis({ viewport$, document$ })\npatchIndeterminate({ document$, tablet$ })\npatchScrollfix({ document$ })\npatchScrolllock({ viewport$, tablet$ })\n\n/* Set up header and main area observable */\nconst header$ = watchHeader(getComponentElement(\"header\"), { viewport$ })\nconst main$ = document$\n .pipe(\n map(() => getComponentElement(\"main\")),\n switchMap(el => watchMain(el, { viewport$, header$ })),\n shareReplay(1)\n )\n\n/* Set up control component observables */\nconst control$ = merge(\n\n /* Consent */\n ...getComponentElements(\"consent\")\n .map(el => mountConsent(el, { target$ })),\n\n /* Dialog */\n ...getComponentElements(\"dialog\")\n .map(el => mountDialog(el, { alert$ })),\n\n /* Color palette */\n ...getComponentElements(\"palette\")\n .map(el => mountPalette(el)),\n\n /* Progress bar */\n ...getComponentElements(\"progress\")\n .map(el => mountProgress(el, { progress$ })),\n\n /* Search */\n ...getComponentElements(\"search\")\n .map(el => mountSearch(el, { index$, keyboard$ })),\n\n /* Repository information */\n ...getComponentElements(\"source\")\n .map(el => mountSource(el))\n)\n\n/* Set up content component observables */\nconst content$ = defer(() => merge(\n\n /* Announcement bar */\n ...getComponentElements(\"announce\")\n .map(el => mountAnnounce(el)),\n\n /* Content */\n ...getComponentElements(\"content\")\n .map(el => mountContent(el, { viewport$, target$, print$ })),\n\n /* Search highlighting */\n ...getComponentElements(\"content\")\n .map(el => feature(\"search.highlight\")\n ? mountSearchHiglight(el, { index$, location$ })\n : EMPTY\n ),\n\n /* Header */\n ...getComponentElements(\"header\")\n .map(el => mountHeader(el, { viewport$, header$, main$ })),\n\n /* Header title */\n ...getComponentElements(\"header-title\")\n .map(el => mountHeaderTitle(el, { viewport$, header$ })),\n\n /* Sidebar */\n ...getComponentElements(\"sidebar\")\n .map(el => el.getAttribute(\"data-md-type\") === \"navigation\"\n ? at(screen$, () => mountSidebar(el, { viewport$, header$, main$ }))\n : at(tablet$, () => mountSidebar(el, { viewport$, header$, main$ }))\n ),\n\n /* Navigation tabs */\n ...getComponentElements(\"tabs\")\n .map(el => mountTabs(el, { viewport$, header$ })),\n\n /* Table of contents */\n ...getComponentElements(\"toc\")\n .map(el => mountTableOfContents(el, {\n viewport$, header$, main$, target$\n })),\n\n /* Back-to-top button */\n ...getComponentElements(\"top\")\n .map(el => mountBackToTop(el, { viewport$, header$, main$, target$ }))\n))\n\n/* Set up component observables */\nconst component$ = document$\n .pipe(\n switchMap(() => content$),\n mergeWith(control$),\n shareReplay(1)\n )\n\n/* Subscribe to all components */\ncomponent$.subscribe()\n\n/* ----------------------------------------------------------------------------\n * Exports\n * ------------------------------------------------------------------------- */\n\nwindow.document$ = document$ /* Document observable */\nwindow.location$ = location$ /* Location subject */\nwindow.target$ = target$ /* Location target observable */\nwindow.keyboard$ = keyboard$ /* Keyboard observable */\nwindow.viewport$ = viewport$ /* Viewport observable */\nwindow.tablet$ = tablet$ /* Media tablet observable */\nwindow.screen$ = screen$ /* Media screen observable */\nwindow.print$ = print$ /* Media print observable */\nwindow.alert$ = alert$ /* Alert subject */\nwindow.progress$ = progress$ /* Progress indicator subject */\nwindow.component$ = component$ /* Component observable */\n", "/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol, Iterator */\n\nvar extendStatics = function(d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n }\n return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n var _, done = false;\n for (var i = decorators.length - 1; i >= 0; i--) {\n var context = {};\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n if (kind === \"accessor\") {\n if (result === void 0) continue;\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n if (_ = accept(result.get)) descriptor.get = _;\n if (_ = accept(result.set)) descriptor.set = _;\n if (_ = accept(result.init)) initializers.unshift(_);\n }\n else if (_ = accept(result)) {\n if (kind === \"field\") initializers.unshift(_);\n else descriptor[key] = _;\n }\n }\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\n done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n var useValue = arguments.length > 2;\n for (var i = 0; i < initializers.length; i++) {\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n }\n return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n}\n\nexport function __generator(thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n for (var ar = [], i = 0; i < arguments.length; i++)\n ar = ar.concat(__read(arguments[i]));\n return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = Object.create((typeof AsyncIterator === \"function\" ? AsyncIterator : Object).prototype), verb(\"next\"), verb(\"throw\"), verb(\"return\", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;\n function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }\n function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n var i, p;\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n};\n\nexport function __importStar(mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n}\n\nexport function __importDefault(mod) {\n return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n if (value !== null && value !== void 0) {\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n var dispose, inner;\n if (async) {\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n dispose = value[Symbol.asyncDispose];\n }\n if (dispose === void 0) {\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n dispose = value[Symbol.dispose];\n if (async) inner = dispose;\n }\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\n env.stack.push({ value: value, dispose: dispose, async: async });\n }\n else if (async) {\n env.stack.push({ async: true });\n }\n return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n function fail(e) {\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n env.hasError = true;\n }\n var r, s = 0;\n function next() {\n while (r = env.stack.pop()) {\n try {\n if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);\n if (r.dispose) {\n var result = r.dispose.call(r.value);\n if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n }\n else s |= 1;\n }\n catch (e) {\n fail(e);\n }\n }\n if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();\n if (env.hasError) throw env.error;\n }\n return next();\n}\n\nexport default {\n __extends,\n __assign,\n __rest,\n __decorate,\n __param,\n __metadata,\n __awaiter,\n __generator,\n __createBinding,\n __exportStar,\n __values,\n __read,\n __spread,\n __spreadArrays,\n __spreadArray,\n __await,\n __asyncGenerator,\n __asyncDelegator,\n __asyncValues,\n __makeTemplateObject,\n __importStar,\n __importDefault,\n __classPrivateFieldGet,\n __classPrivateFieldSet,\n __classPrivateFieldIn,\n __addDisposableResource,\n __disposeResources,\n};\n", "/**\n * Returns true if the object is a function.\n * @param value The value to check\n */\nexport function isFunction(value: any): value is (...args: any[]) => any {\n return typeof value === 'function';\n}\n", "/**\n * Used to create Error subclasses until the community moves away from ES5.\n *\n * This is because compiling from TypeScript down to ES5 has issues with subclassing Errors\n * as well as other built-in types: https://github.com/Microsoft/TypeScript/issues/12123\n *\n * @param createImpl A factory function to create the actual constructor implementation. The returned\n * function should be a named function that calls `_super` internally.\n */\nexport function createErrorClass(createImpl: (_super: any) => any): T {\n const _super = (instance: any) => {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n\n const ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface UnsubscriptionError extends Error {\n readonly errors: any[];\n}\n\nexport interface UnsubscriptionErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (errors: any[]): UnsubscriptionError;\n}\n\n/**\n * An error thrown when one or more errors have occurred during the\n * `unsubscribe` of a {@link Subscription}.\n */\nexport const UnsubscriptionError: UnsubscriptionErrorCtor = createErrorClass(\n (_super) =>\n function UnsubscriptionErrorImpl(this: any, errors: (Error | string)[]) {\n _super(this);\n this.message = errors\n ? `${errors.length} errors occurred during unsubscription:\n${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n ')}`\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n }\n);\n", "/**\n * Removes an item from an array, mutating it.\n * @param arr The array to remove the item from\n * @param item The item to remove\n */\nexport function arrRemove(arr: T[] | undefined | null, item: T) {\n if (arr) {\n const index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { SubscriptionLike, TeardownLogic, Unsubscribable } from './types';\nimport { arrRemove } from './util/arrRemove';\n\n/**\n * Represents a disposable resource, such as the execution of an Observable. A\n * Subscription has one important method, `unsubscribe`, that takes no argument\n * and just disposes the resource held by the subscription.\n *\n * Additionally, subscriptions may be grouped together through the `add()`\n * method, which will attach a child Subscription to the current Subscription.\n * When a Subscription is unsubscribed, all its children (and its grandchildren)\n * will be unsubscribed as well.\n *\n * @class Subscription\n */\nexport class Subscription implements SubscriptionLike {\n /** @nocollapse */\n public static EMPTY = (() => {\n const empty = new Subscription();\n empty.closed = true;\n return empty;\n })();\n\n /**\n * A flag to indicate whether this Subscription has already been unsubscribed.\n */\n public closed = false;\n\n private _parentage: Subscription[] | Subscription | null = null;\n\n /**\n * The list of registered finalizers to execute upon unsubscription. Adding and removing from this\n * list occurs in the {@link #add} and {@link #remove} methods.\n */\n private _finalizers: Exclude[] | null = null;\n\n /**\n * @param initialTeardown A function executed first as part of the finalization\n * process that is kicked off when {@link #unsubscribe} is called.\n */\n constructor(private initialTeardown?: () => void) {}\n\n /**\n * Disposes the resources held by the subscription. May, for instance, cancel\n * an ongoing Observable execution or cancel any other type of work that\n * started when the Subscription was created.\n * @return {void}\n */\n unsubscribe(): void {\n let errors: any[] | undefined;\n\n if (!this.closed) {\n this.closed = true;\n\n // Remove this from it's parents.\n const { _parentage } = this;\n if (_parentage) {\n this._parentage = null;\n if (Array.isArray(_parentage)) {\n for (const parent of _parentage) {\n parent.remove(this);\n }\n } else {\n _parentage.remove(this);\n }\n }\n\n const { initialTeardown: initialFinalizer } = this;\n if (isFunction(initialFinalizer)) {\n try {\n initialFinalizer();\n } catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n\n const { _finalizers } = this;\n if (_finalizers) {\n this._finalizers = null;\n for (const finalizer of _finalizers) {\n try {\n execFinalizer(finalizer);\n } catch (err) {\n errors = errors ?? [];\n if (err instanceof UnsubscriptionError) {\n errors = [...errors, ...err.errors];\n } else {\n errors.push(err);\n }\n }\n }\n }\n\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n }\n\n /**\n * Adds a finalizer to this subscription, so that finalization will be unsubscribed/called\n * when this subscription is unsubscribed. If this subscription is already {@link #closed},\n * because it has already been unsubscribed, then whatever finalizer is passed to it\n * will automatically be executed (unless the finalizer itself is also a closed subscription).\n *\n * Closed Subscriptions cannot be added as finalizers to any subscription. Adding a closed\n * subscription to a any subscription will result in no operation. (A noop).\n *\n * Adding a subscription to itself, or adding `null` or `undefined` will not perform any\n * operation at all. (A noop).\n *\n * `Subscription` instances that are added to this instance will automatically remove themselves\n * if they are unsubscribed. Functions and {@link Unsubscribable} objects that you wish to remove\n * will need to be removed manually with {@link #remove}\n *\n * @param teardown The finalization logic to add to this subscription.\n */\n add(teardown: TeardownLogic): void {\n // Only add the finalizer if it's not undefined\n // and don't add a subscription to itself.\n if (teardown && teardown !== this) {\n if (this.closed) {\n // If this subscription is already closed,\n // execute whatever finalizer is handed to it automatically.\n execFinalizer(teardown);\n } else {\n if (teardown instanceof Subscription) {\n // We don't add closed subscriptions, and we don't add the same subscription\n // twice. Subscription unsubscribe is idempotent.\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._finalizers = this._finalizers ?? []).push(teardown);\n }\n }\n }\n\n /**\n * Checks to see if a this subscription already has a particular parent.\n * This will signal that this subscription has already been added to the parent in question.\n * @param parent the parent to check for\n */\n private _hasParent(parent: Subscription) {\n const { _parentage } = this;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n }\n\n /**\n * Adds a parent to this subscription so it can be removed from the parent if it\n * unsubscribes on it's own.\n *\n * NOTE: THIS ASSUMES THAT {@link _hasParent} HAS ALREADY BEEN CHECKED.\n * @param parent The parent subscription to add\n */\n private _addParent(parent: Subscription) {\n const { _parentage } = this;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n }\n\n /**\n * Called on a child when it is removed via {@link #remove}.\n * @param parent The parent to remove\n */\n private _removeParent(parent: Subscription) {\n const { _parentage } = this;\n if (_parentage === parent) {\n this._parentage = null;\n } else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n }\n\n /**\n * Removes a finalizer from this subscription that was previously added with the {@link #add} method.\n *\n * Note that `Subscription` instances, when unsubscribed, will automatically remove themselves\n * from every other `Subscription` they have been added to. This means that using the `remove` method\n * is not a common thing and should be used thoughtfully.\n *\n * If you add the same finalizer instance of a function or an unsubscribable object to a `Subscription` instance\n * more than once, you will need to call `remove` the same number of times to remove all instances.\n *\n * All finalizer instances are removed to free up memory upon unsubscription.\n *\n * @param teardown The finalizer to remove from this subscription\n */\n remove(teardown: Exclude): void {\n const { _finalizers } = this;\n _finalizers && arrRemove(_finalizers, teardown);\n\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n }\n}\n\nexport const EMPTY_SUBSCRIPTION = Subscription.EMPTY;\n\nexport function isSubscription(value: any): value is Subscription {\n return (\n value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe))\n );\n}\n\nfunction execFinalizer(finalizer: Unsubscribable | (() => void)) {\n if (isFunction(finalizer)) {\n finalizer();\n } else {\n finalizer.unsubscribe();\n }\n}\n", "import { Subscriber } from './Subscriber';\nimport { ObservableNotification } from './types';\n\n/**\n * The {@link GlobalConfig} object for RxJS. It is used to configure things\n * like how to react on unhandled errors.\n */\nexport const config: GlobalConfig = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n\n/**\n * The global configuration object for RxJS, used to configure things\n * like how to react on unhandled errors. Accessible via {@link config}\n * object.\n */\nexport interface GlobalConfig {\n /**\n * A registration point for unhandled errors from RxJS. These are errors that\n * cannot were not handled by consuming code in the usual subscription path. For\n * example, if you have this configured, and you subscribe to an observable without\n * providing an error handler, errors from that subscription will end up here. This\n * will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onUnhandledError: ((err: any) => void) | null;\n\n /**\n * A registration point for notifications that cannot be sent to subscribers because they\n * have completed, errored or have been explicitly unsubscribed. By default, next, complete\n * and error notifications sent to stopped subscribers are noops. However, sometimes callers\n * might want a different behavior. For example, with sources that attempt to report errors\n * to stopped subscribers, a caller can configure RxJS to throw an unhandled error instead.\n * This will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onStoppedNotification: ((notification: ObservableNotification, subscriber: Subscriber) => void) | null;\n\n /**\n * The promise constructor used by default for {@link Observable#toPromise toPromise} and {@link Observable#forEach forEach}\n * methods.\n *\n * @deprecated As of version 8, RxJS will no longer support this sort of injection of a\n * Promise constructor. If you need a Promise implementation other than native promises,\n * please polyfill/patch Promise as you see appropriate. Will be removed in v8.\n */\n Promise?: PromiseConstructorLike;\n\n /**\n * If true, turns on synchronous error rethrowing, which is a deprecated behavior\n * in v6 and higher. This behavior enables bad patterns like wrapping a subscribe\n * call in a try/catch block. It also enables producer interference, a nasty bug\n * where a multicast can be broken for all observers by a downstream consumer with\n * an unhandled error. DO NOT USE THIS FLAG UNLESS IT'S NEEDED TO BUY TIME\n * FOR MIGRATION REASONS.\n *\n * @deprecated As of version 8, RxJS will no longer support synchronous throwing\n * of unhandled errors. All errors will be thrown on a separate call stack to prevent bad\n * behaviors described above. Will be removed in v8.\n */\n useDeprecatedSynchronousErrorHandling: boolean;\n\n /**\n * If true, enables an as-of-yet undocumented feature from v5: The ability to access\n * `unsubscribe()` via `this` context in `next` functions created in observers passed\n * to `subscribe`.\n *\n * This is being removed because the performance was severely problematic, and it could also cause\n * issues when types other than POJOs are passed to subscribe as subscribers, as they will likely have\n * their `this` context overwritten.\n *\n * @deprecated As of version 8, RxJS will no longer support altering the\n * context of next functions provided as part of an observer to Subscribe. Instead,\n * you will have access to a subscription or a signal or token that will allow you to do things like\n * unsubscribe and test closed status. Will be removed in v8.\n */\n useDeprecatedNextContext: boolean;\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetTimeoutFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearTimeoutFunction = (handle: TimerHandle) => void;\n\ninterface TimeoutProvider {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n delegate:\n | {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n }\n | undefined;\n}\n\nexport const timeoutProvider: TimeoutProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setTimeout(handler: () => void, timeout?: number, ...args) {\n const { delegate } = timeoutProvider;\n if (delegate?.setTimeout) {\n return delegate.setTimeout(handler, timeout, ...args);\n }\n return setTimeout(handler, timeout, ...args);\n },\n clearTimeout(handle) {\n const { delegate } = timeoutProvider;\n return (delegate?.clearTimeout || clearTimeout)(handle as any);\n },\n delegate: undefined,\n};\n", "import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\n\n/**\n * Handles an error on another job either with the user-configured {@link onUnhandledError},\n * or by throwing it on that new job so it can be picked up by `window.onerror`, `process.on('error')`, etc.\n *\n * This should be called whenever there is an error that is out-of-band with the subscription\n * or when an error hits a terminal boundary of the subscription and no error handler was provided.\n *\n * @param err the error to report\n */\nexport function reportUnhandledError(err: any) {\n timeoutProvider.setTimeout(() => {\n const { onUnhandledError } = config;\n if (onUnhandledError) {\n // Execute the user-configured error handler.\n onUnhandledError(err);\n } else {\n // Throw so it is picked up by the runtime's uncaught error mechanism.\n throw err;\n }\n });\n}\n", "/* tslint:disable:no-empty */\nexport function noop() { }\n", "import { CompleteNotification, NextNotification, ErrorNotification } from './types';\n\n/**\n * A completion object optimized for memory use and created to be the\n * same \"shape\" as other notifications in v8.\n * @internal\n */\nexport const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined) as CompleteNotification)();\n\n/**\n * Internal use only. Creates an optimized error notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function errorNotification(error: any): ErrorNotification {\n return createNotification('E', undefined, error) as any;\n}\n\n/**\n * Internal use only. Creates an optimized next notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function nextNotification(value: T) {\n return createNotification('N', value, undefined) as NextNotification;\n}\n\n/**\n * Ensures that all notifications created internally have the same \"shape\" in v8.\n *\n * TODO: This is only exported to support a crazy legacy test in `groupBy`.\n * @internal\n */\nexport function createNotification(kind: 'N' | 'E' | 'C', value: any, error: any) {\n return {\n kind,\n value,\n error,\n };\n}\n", "import { config } from '../config';\n\nlet context: { errorThrown: boolean; error: any } | null = null;\n\n/**\n * Handles dealing with errors for super-gross mode. Creates a context, in which\n * any synchronously thrown errors will be passed to {@link captureError}. Which\n * will record the error such that it will be rethrown after the call back is complete.\n * TODO: Remove in v8\n * @param cb An immediately executed function.\n */\nexport function errorContext(cb: () => void) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n const isRoot = !context;\n if (isRoot) {\n context = { errorThrown: false, error: null };\n }\n cb();\n if (isRoot) {\n const { errorThrown, error } = context!;\n context = null;\n if (errorThrown) {\n throw error;\n }\n }\n } else {\n // This is the general non-deprecated path for everyone that\n // isn't crazy enough to use super-gross mode (useDeprecatedSynchronousErrorHandling)\n cb();\n }\n}\n\n/**\n * Captures errors only in super-gross mode.\n * @param err the error to capture\n */\nexport function captureError(err: any) {\n if (config.useDeprecatedSynchronousErrorHandling && context) {\n context.errorThrown = true;\n context.error = err;\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { Observer, ObservableNotification } from './types';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nimport { captureError } from './util/errorContext';\n\n/**\n * Implements the {@link Observer} interface and extends the\n * {@link Subscription} class. While the {@link Observer} is the public API for\n * consuming the values of an {@link Observable}, all Observers get converted to\n * a Subscriber, in order to provide Subscription-like capabilities such as\n * `unsubscribe`. Subscriber is a common type in RxJS, and crucial for\n * implementing operators, but it is rarely used as a public API.\n *\n * @class Subscriber\n */\nexport class Subscriber extends Subscription implements Observer {\n /**\n * A static factory for a Subscriber, given a (potentially partial) definition\n * of an Observer.\n * @param next The `next` callback of an Observer.\n * @param error The `error` callback of an\n * Observer.\n * @param complete The `complete` callback of an\n * Observer.\n * @return A Subscriber wrapping the (partially defined)\n * Observer represented by the given arguments.\n * @nocollapse\n * @deprecated Do not use. Will be removed in v8. There is no replacement for this\n * method, and there is no reason to be creating instances of `Subscriber` directly.\n * If you have a specific use case, please file an issue.\n */\n static create(next?: (x?: T) => void, error?: (e?: any) => void, complete?: () => void): Subscriber {\n return new SafeSubscriber(next, error, complete);\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected isStopped: boolean = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected destination: Subscriber | Observer; // this `any` is the escape hatch to erase extra type param (e.g. R)\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * There is no reason to directly create an instance of Subscriber. This type is exported for typings reasons.\n */\n constructor(destination?: Subscriber | Observer) {\n super();\n if (destination) {\n this.destination = destination;\n // Automatically chain subscriptions together here.\n // if destination is a Subscription, then it is a Subscriber.\n if (isSubscription(destination)) {\n destination.add(this);\n }\n } else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `next` from\n * the Observable, with a value. The Observable may call this method 0 or more\n * times.\n * @param {T} [value] The `next` value.\n * @return {void}\n */\n next(value?: T): void {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n } else {\n this._next(value!);\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `error` from\n * the Observable, with an attached `Error`. Notifies the Observer that\n * the Observable has experienced an error condition.\n * @param {any} [err] The `error` exception.\n * @return {void}\n */\n error(err?: any): void {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n } else {\n this.isStopped = true;\n this._error(err);\n }\n }\n\n /**\n * The {@link Observer} callback to receive a valueless notification of type\n * `complete` from the Observable. Notifies the Observer that the Observable\n * has finished sending push-based notifications.\n * @return {void}\n */\n complete(): void {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n } else {\n this.isStopped = true;\n this._complete();\n }\n }\n\n unsubscribe(): void {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n this.destination = null!;\n }\n }\n\n protected _next(value: T): void {\n this.destination.next(value);\n }\n\n protected _error(err: any): void {\n try {\n this.destination.error(err);\n } finally {\n this.unsubscribe();\n }\n }\n\n protected _complete(): void {\n try {\n this.destination.complete();\n } finally {\n this.unsubscribe();\n }\n }\n}\n\n/**\n * This bind is captured here because we want to be able to have\n * compatibility with monoid libraries that tend to use a method named\n * `bind`. In particular, a library called Monio requires this.\n */\nconst _bind = Function.prototype.bind;\n\nfunction bind any>(fn: Fn, thisArg: any): Fn {\n return _bind.call(fn, thisArg);\n}\n\n/**\n * Internal optimization only, DO NOT EXPOSE.\n * @internal\n */\nclass ConsumerObserver implements Observer {\n constructor(private partialObserver: Partial>) {}\n\n next(value: T): void {\n const { partialObserver } = this;\n if (partialObserver.next) {\n try {\n partialObserver.next(value);\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n\n error(err: any): void {\n const { partialObserver } = this;\n if (partialObserver.error) {\n try {\n partialObserver.error(err);\n } catch (error) {\n handleUnhandledError(error);\n }\n } else {\n handleUnhandledError(err);\n }\n }\n\n complete(): void {\n const { partialObserver } = this;\n if (partialObserver.complete) {\n try {\n partialObserver.complete();\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n}\n\nexport class SafeSubscriber extends Subscriber {\n constructor(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((e?: any) => void) | null,\n complete?: (() => void) | null\n ) {\n super();\n\n let partialObserver: Partial>;\n if (isFunction(observerOrNext) || !observerOrNext) {\n // The first argument is a function, not an observer. The next\n // two arguments *could* be observers, or they could be empty.\n partialObserver = {\n next: (observerOrNext ?? undefined) as (((value: T) => void) | undefined),\n error: error ?? undefined,\n complete: complete ?? undefined,\n };\n } else {\n // The first argument is a partial observer.\n let context: any;\n if (this && config.useDeprecatedNextContext) {\n // This is a deprecated path that made `this.unsubscribe()` available in\n // next handler functions passed to subscribe. This only exists behind a flag\n // now, as it is *very* slow.\n context = Object.create(observerOrNext);\n context.unsubscribe = () => this.unsubscribe();\n partialObserver = {\n next: observerOrNext.next && bind(observerOrNext.next, context),\n error: observerOrNext.error && bind(observerOrNext.error, context),\n complete: observerOrNext.complete && bind(observerOrNext.complete, context),\n };\n } else {\n // The \"normal\" path. Just use the partial observer directly.\n partialObserver = observerOrNext;\n }\n }\n\n // Wrap the partial observer to ensure it's a full observer, and\n // make sure proper error handling is accounted for.\n this.destination = new ConsumerObserver(partialObserver);\n }\n}\n\nfunction handleUnhandledError(error: any) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n captureError(error);\n } else {\n // Ideal path, we report this as an unhandled error,\n // which is thrown on a new call stack.\n reportUnhandledError(error);\n }\n}\n\n/**\n * An error handler used when no error handler was supplied\n * to the SafeSubscriber -- meaning no error handler was supplied\n * do the `subscribe` call on our observable.\n * @param err The error to handle\n */\nfunction defaultErrorHandler(err: any) {\n throw err;\n}\n\n/**\n * A handler for notifications that cannot be sent to a stopped subscriber.\n * @param notification The notification being sent\n * @param subscriber The stopped subscriber\n */\nfunction handleStoppedNotification(notification: ObservableNotification, subscriber: Subscriber) {\n const { onStoppedNotification } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\n\n/**\n * The observer used as a stub for subscriptions where the user did not\n * pass any arguments to `subscribe`. Comes with the default error handling\n * behavior.\n */\nexport const EMPTY_OBSERVER: Readonly> & { closed: true } = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n", "/**\n * Symbol.observable or a string \"@@observable\". Used for interop\n *\n * @deprecated We will no longer be exporting this symbol in upcoming versions of RxJS.\n * Instead polyfill and use Symbol.observable directly *or* use https://www.npmjs.com/package/symbol-observable\n */\nexport const observable: string | symbol = (() => (typeof Symbol === 'function' && Symbol.observable) || '@@observable')();\n", "/**\n * This function takes one parameter and just returns it. Simply put,\n * this is like `(x: T): T => x`.\n *\n * ## Examples\n *\n * This is useful in some cases when using things like `mergeMap`\n *\n * ```ts\n * import { interval, take, map, range, mergeMap, identity } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(5));\n *\n * const result$ = source$.pipe(\n * map(i => range(i)),\n * mergeMap(identity) // same as mergeMap(x => x)\n * );\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * Or when you want to selectively apply an operator\n *\n * ```ts\n * import { interval, take, identity } from 'rxjs';\n *\n * const shouldLimit = () => Math.random() < 0.5;\n *\n * const source$ = interval(1000);\n *\n * const result$ = source$.pipe(shouldLimit() ? take(5) : identity);\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * @param x Any value that is returned by this function\n * @returns The value passed as the first parameter to this function\n */\nexport function identity(x: T): T {\n return x;\n}\n", "import { identity } from './identity';\nimport { UnaryFunction } from '../types';\n\nexport function pipe(): typeof identity;\nexport function pipe(fn1: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction, fn3: UnaryFunction): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction,\n ...fns: UnaryFunction[]\n): UnaryFunction;\n\n/**\n * pipe() can be called on one or more functions, each of which can take one argument (\"UnaryFunction\")\n * and uses it to return a value.\n * It returns a function that takes one argument, passes it to the first UnaryFunction, and then\n * passes the result to the next one, passes that result to the next one, and so on. \n */\nexport function pipe(...fns: Array>): UnaryFunction {\n return pipeFromArray(fns);\n}\n\n/** @internal */\nexport function pipeFromArray(fns: Array>): UnaryFunction {\n if (fns.length === 0) {\n return identity as UnaryFunction;\n }\n\n if (fns.length === 1) {\n return fns[0];\n }\n\n return function piped(input: T): R {\n return fns.reduce((prev: any, fn: UnaryFunction) => fn(prev), input as any);\n };\n}\n", "import { Operator } from './Operator';\nimport { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription, Subscription } from './Subscription';\nimport { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A representation of any set of values over any amount of time. This is the most basic building block\n * of RxJS.\n *\n * @class Observable\n */\nexport class Observable implements Subscribable {\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n source: Observable | undefined;\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n operator: Operator | undefined;\n\n /**\n * @constructor\n * @param {Function} subscribe the function that is called when the Observable is\n * initially subscribed to. This function is given a Subscriber, to which new values\n * can be `next`ed, or an `error` method can be called to raise an error, or\n * `complete` can be called to notify of a successful completion.\n */\n constructor(subscribe?: (this: Observable, subscriber: Subscriber) => TeardownLogic) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n\n // HACK: Since TypeScript inherits static properties too, we have to\n // fight against TypeScript here so Subject can have a different static create signature\n /**\n * Creates a new Observable by calling the Observable constructor\n * @owner Observable\n * @method create\n * @param {Function} subscribe? the subscriber function to be passed to the Observable constructor\n * @return {Observable} a new observable\n * @nocollapse\n * @deprecated Use `new Observable()` instead. Will be removed in v8.\n */\n static create: (...args: any[]) => any = (subscribe?: (subscriber: Subscriber) => TeardownLogic) => {\n return new Observable(subscribe);\n };\n\n /**\n * Creates a new Observable, with this Observable instance as the source, and the passed\n * operator defined as the new observable's operator.\n * @method lift\n * @param operator the operator defining the operation to take on the observable\n * @return a new observable with the Operator applied\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * If you have implemented an operator using `lift`, it is recommended that you create an\n * operator by simply returning `new Observable()` directly. See \"Creating new operators from\n * scratch\" section here: https://rxjs.dev/guide/operators\n */\n lift(operator?: Operator): Observable {\n const observable = new Observable();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n\n subscribe(observerOrNext?: Partial> | ((value: T) => void)): Subscription;\n /** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */\n subscribe(next?: ((value: T) => void) | null, error?: ((error: any) => void) | null, complete?: (() => void) | null): Subscription;\n /**\n * Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.\n *\n * Use it when you have all these Observables, but still nothing is happening.\n *\n * `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It\n * might be for example a function that you passed to Observable's constructor, but most of the time it is\n * a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means\n * that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often\n * the thought.\n *\n * Apart from starting the execution of an Observable, this method allows you to listen for values\n * that an Observable emits, as well as for when it completes or errors. You can achieve this in two\n * of the following ways.\n *\n * The first way is creating an object that implements {@link Observer} interface. It should have methods\n * defined by that interface, but note that it should be just a regular JavaScript object, which you can create\n * yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do\n * not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also\n * that your object does not have to implement all methods. If you find yourself creating a method that doesn't\n * do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,\n * it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,\n * use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or\n * `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide\n * an `error` method to avoid missing thrown errors.\n *\n * The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.\n * This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent\n * of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,\n * if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,\n * since `subscribe` recognizes these functions by where they were placed in function call. When it comes\n * to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.\n *\n * You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events\n * and you also handled emissions internally by using operators (e.g. using `tap`).\n *\n * Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.\n * This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean\n * up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback\n * provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.\n *\n * Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.\n * It is an Observable itself that decides when these functions will be called. For example {@link of}\n * by default emits all its values synchronously. Always check documentation for how given Observable\n * will behave when subscribed and if its default behavior can be modified with a `scheduler`.\n *\n * #### Examples\n *\n * Subscribe with an {@link guide/observer Observer}\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * const sumObserver = {\n * sum: 0,\n * next(value) {\n * console.log('Adding: ' + value);\n * this.sum = this.sum + value;\n * },\n * error() {\n * // We actually could just remove this method,\n * // since we do not really care about errors right now.\n * },\n * complete() {\n * console.log('Sum equals: ' + this.sum);\n * }\n * };\n *\n * of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.\n * .subscribe(sumObserver);\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Subscribe with functions ({@link deprecations/subscribe-arguments deprecated})\n *\n * ```ts\n * import { of } from 'rxjs'\n *\n * let sum = 0;\n *\n * of(1, 2, 3).subscribe(\n * value => {\n * console.log('Adding: ' + value);\n * sum = sum + value;\n * },\n * undefined,\n * () => console.log('Sum equals: ' + sum)\n * );\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Cancel a subscription\n *\n * ```ts\n * import { interval } from 'rxjs';\n *\n * const subscription = interval(1000).subscribe({\n * next(num) {\n * console.log(num)\n * },\n * complete() {\n * // Will not be called, even when cancelling subscription.\n * console.log('completed!');\n * }\n * });\n *\n * setTimeout(() => {\n * subscription.unsubscribe();\n * console.log('unsubscribed!');\n * }, 2500);\n *\n * // Logs:\n * // 0 after 1s\n * // 1 after 2s\n * // 'unsubscribed!' after 2.5s\n * ```\n *\n * @param {Observer|Function} observerOrNext (optional) Either an observer with methods to be called,\n * or the first of three possible handlers, which is the handler for each value emitted from the subscribed\n * Observable.\n * @param {Function} error (optional) A handler for a terminal event resulting from an error. If no error handler is provided,\n * the error will be thrown asynchronously as unhandled.\n * @param {Function} complete (optional) A handler for a terminal event resulting from successful completion.\n * @return {Subscription} a subscription reference to the registered handlers\n * @method subscribe\n */\n subscribe(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((error: any) => void) | null,\n complete?: (() => void) | null\n ): Subscription {\n const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n\n errorContext(() => {\n const { operator, source } = this;\n subscriber.add(\n operator\n ? // We're dealing with a subscription in the\n // operator chain to one of our lifted operators.\n operator.call(subscriber, source)\n : source\n ? // If `source` has a value, but `operator` does not, something that\n // had intimate knowledge of our API, like our `Subject`, must have\n // set it. We're going to just call `_subscribe` directly.\n this._subscribe(subscriber)\n : // In all other cases, we're likely wrapping a user-provided initializer\n // function, so we need to catch errors and handle them appropriately.\n this._trySubscribe(subscriber)\n );\n });\n\n return subscriber;\n }\n\n /** @internal */\n protected _trySubscribe(sink: Subscriber): TeardownLogic {\n try {\n return this._subscribe(sink);\n } catch (err) {\n // We don't need to return anything in this case,\n // because it's just going to try to `add()` to a subscription\n // above.\n sink.error(err);\n }\n }\n\n /**\n * Used as a NON-CANCELLABLE means of subscribing to an observable, for use with\n * APIs that expect promises, like `async/await`. You cannot unsubscribe from this.\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * #### Example\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(4));\n *\n * async function getTotal() {\n * let total = 0;\n *\n * await source$.forEach(value => {\n * total += value;\n * console.log('observable -> ' + value);\n * });\n *\n * return total;\n * }\n *\n * getTotal().then(\n * total => console.log('Total: ' + total)\n * );\n *\n * // Expected:\n * // 'observable -> 0'\n * // 'observable -> 1'\n * // 'observable -> 2'\n * // 'observable -> 3'\n * // 'Total: 6'\n * ```\n *\n * @param next a handler for each value emitted by the observable\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n */\n forEach(next: (value: T) => void): Promise;\n\n /**\n * @param next a handler for each value emitted by the observable\n * @param promiseCtor a constructor function used to instantiate the Promise\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n * @deprecated Passing a Promise constructor will no longer be available\n * in upcoming versions of RxJS. This is because it adds weight to the library, for very\n * little benefit. If you need this functionality, it is recommended that you either\n * polyfill Promise, or you create an adapter to convert the returned native promise\n * to whatever promise implementation you wanted. Will be removed in v8.\n */\n forEach(next: (value: T) => void, promiseCtor: PromiseConstructorLike): Promise;\n\n forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n const subscriber = new SafeSubscriber({\n next: (value) => {\n try {\n next(value);\n } catch (err) {\n reject(err);\n subscriber.unsubscribe();\n }\n },\n error: reject,\n complete: resolve,\n });\n this.subscribe(subscriber);\n }) as Promise;\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): TeardownLogic {\n return this.source?.subscribe(subscriber);\n }\n\n /**\n * An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable\n * @method Symbol.observable\n * @return {Observable} this instance of the observable\n */\n [Symbol_observable]() {\n return this;\n }\n\n /* tslint:disable:max-line-length */\n pipe(): Observable;\n pipe(op1: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction,\n ...operations: OperatorFunction[]\n ): Observable;\n /* tslint:enable:max-line-length */\n\n /**\n * Used to stitch together functional operators into a chain.\n * @method pipe\n * @return {Observable} the Observable result of all of the operators having\n * been called in the order they were passed in.\n *\n * ## Example\n *\n * ```ts\n * import { interval, filter, map, scan } from 'rxjs';\n *\n * interval(1000)\n * .pipe(\n * filter(x => x % 2 === 0),\n * map(x => x + x),\n * scan((acc, x) => acc + x)\n * )\n * .subscribe(x => console.log(x));\n * ```\n */\n pipe(...operations: OperatorFunction[]): Observable {\n return pipeFromArray(operations)(this);\n }\n\n /* tslint:disable:max-line-length */\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: typeof Promise): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: PromiseConstructorLike): Promise;\n /* tslint:enable:max-line-length */\n\n /**\n * Subscribe to this Observable and get a Promise resolving on\n * `complete` with the last emission (if any).\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * @method toPromise\n * @param [promiseCtor] a constructor function used to instantiate\n * the Promise\n * @return A Promise that resolves with the last value emit, or\n * rejects on an error. If there were no emissions, Promise\n * resolves with undefined.\n * @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise\n */\n toPromise(promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n let value: T | undefined;\n this.subscribe(\n (x: T) => (value = x),\n (err: any) => reject(err),\n () => resolve(value)\n );\n }) as Promise;\n }\n}\n\n/**\n * Decides between a passed promise constructor from consuming code,\n * A default configured promise constructor, and the native promise\n * constructor and returns it. If nothing can be found, it will throw\n * an error.\n * @param promiseCtor The optional promise constructor to passed by consuming code\n */\nfunction getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) {\n return promiseCtor ?? config.Promise ?? Promise;\n}\n\nfunction isObserver(value: any): value is Observer {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\n\nfunction isSubscriber(value: any): value is Subscriber {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n", "import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { OperatorFunction } from '../types';\nimport { isFunction } from './isFunction';\n\n/**\n * Used to determine if an object is an Observable with a lift function.\n */\nexport function hasLift(source: any): source is { lift: InstanceType['lift'] } {\n return isFunction(source?.lift);\n}\n\n/**\n * Creates an `OperatorFunction`. Used to define operators throughout the library in a concise way.\n * @param init The logic to connect the liftedSource to the subscriber at the moment of subscription.\n */\nexport function operate(\n init: (liftedSource: Observable, subscriber: Subscriber) => (() => void) | void\n): OperatorFunction {\n return (source: Observable) => {\n if (hasLift(source)) {\n return source.lift(function (this: Subscriber, liftedSource: Observable) {\n try {\n return init(liftedSource, this);\n } catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n", "import { Subscriber } from '../Subscriber';\n\n/**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional teardown logic here. This will only be called on teardown if the\n * subscriber itself is not already closed. This is called after all other teardown logic is executed.\n */\nexport function createOperatorSubscriber(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n onFinalize?: () => void\n): Subscriber {\n return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);\n}\n\n/**\n * A generic helper for allowing operators to be created with a Subscriber and\n * use closures to capture necessary state from the operator function itself.\n */\nexport class OperatorSubscriber extends Subscriber {\n /**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional finalization logic here. This will only be called on finalization if the\n * subscriber itself is not already closed. This is called after all other finalization logic is executed.\n * @param shouldUnsubscribe An optional check to see if an unsubscribe call should truly unsubscribe.\n * NOTE: This currently **ONLY** exists to support the strange behavior of {@link groupBy}, where unsubscription\n * to the resulting observable does not actually disconnect from the source if there are active subscriptions\n * to any grouped observable. (DO NOT EXPOSE OR USE EXTERNALLY!!!)\n */\n constructor(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n private onFinalize?: () => void,\n private shouldUnsubscribe?: () => boolean\n ) {\n // It's important - for performance reasons - that all of this class's\n // members are initialized and that they are always initialized in the same\n // order. This will ensure that all OperatorSubscriber instances have the\n // same hidden class in V8. This, in turn, will help keep the number of\n // hidden classes involved in property accesses within the base class as\n // low as possible. If the number of hidden classes involved exceeds four,\n // the property accesses will become megamorphic and performance penalties\n // will be incurred - i.e. inline caches won't be used.\n //\n // The reasons for ensuring all instances have the same hidden class are\n // further discussed in this blog post from Benedikt Meurer:\n // https://benediktmeurer.de/2018/03/23/impact-of-polymorphism-on-component-based-frameworks-like-react/\n super(destination);\n this._next = onNext\n ? function (this: OperatorSubscriber, value: T) {\n try {\n onNext(value);\n } catch (err) {\n destination.error(err);\n }\n }\n : super._next;\n this._error = onError\n ? function (this: OperatorSubscriber, err: any) {\n try {\n onError(err);\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._error;\n this._complete = onComplete\n ? function (this: OperatorSubscriber) {\n try {\n onComplete();\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._complete;\n }\n\n unsubscribe() {\n if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {\n const { closed } = this;\n super.unsubscribe();\n // Execute additional teardown if we have any and we didn't already do so.\n !closed && this.onFinalize?.();\n }\n }\n}\n", "import { Subscription } from '../Subscription';\n\ninterface AnimationFrameProvider {\n schedule(callback: FrameRequestCallback): Subscription;\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n delegate:\n | {\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n }\n | undefined;\n}\n\nexport const animationFrameProvider: AnimationFrameProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n schedule(callback) {\n let request = requestAnimationFrame;\n let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame;\n const { delegate } = animationFrameProvider;\n if (delegate) {\n request = delegate.requestAnimationFrame;\n cancel = delegate.cancelAnimationFrame;\n }\n const handle = request((timestamp) => {\n // Clear the cancel function. The request has been fulfilled, so\n // attempting to cancel the request upon unsubscription would be\n // pointless.\n cancel = undefined;\n callback(timestamp);\n });\n return new Subscription(() => cancel?.(handle));\n },\n requestAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args);\n },\n cancelAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args);\n },\n delegate: undefined,\n};\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface ObjectUnsubscribedError extends Error {}\n\nexport interface ObjectUnsubscribedErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (): ObjectUnsubscribedError;\n}\n\n/**\n * An error thrown when an action is invalid because the object has been\n * unsubscribed.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n *\n * @class ObjectUnsubscribedError\n */\nexport const ObjectUnsubscribedError: ObjectUnsubscribedErrorCtor = createErrorClass(\n (_super) =>\n function ObjectUnsubscribedErrorImpl(this: any) {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n }\n);\n", "import { Operator } from './Operator';\nimport { Observable } from './Observable';\nimport { Subscriber } from './Subscriber';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { Observer, SubscriptionLike, TeardownLogic } from './types';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A Subject is a special type of Observable that allows values to be\n * multicasted to many Observers. Subjects are like EventEmitters.\n *\n * Every Subject is an Observable and an Observer. You can subscribe to a\n * Subject, and you can call next to feed values as well as error and complete.\n */\nexport class Subject extends Observable implements SubscriptionLike {\n closed = false;\n\n private currentObservers: Observer[] | null = null;\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n observers: Observer[] = [];\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n isStopped = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n hasError = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n thrownError: any = null;\n\n /**\n * Creates a \"subject\" by basically gluing an observer to an observable.\n *\n * @nocollapse\n * @deprecated Recommended you do not use. Will be removed at some point in the future. Plans for replacement still under discussion.\n */\n static create: (...args: any[]) => any = (destination: Observer, source: Observable): AnonymousSubject => {\n return new AnonymousSubject(destination, source);\n };\n\n constructor() {\n // NOTE: This must be here to obscure Observable's constructor.\n super();\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n lift(operator: Operator): Observable {\n const subject = new AnonymousSubject(this, this);\n subject.operator = operator as any;\n return subject as any;\n }\n\n /** @internal */\n protected _throwIfClosed() {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n }\n\n next(value: T) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n if (!this.currentObservers) {\n this.currentObservers = Array.from(this.observers);\n }\n for (const observer of this.currentObservers) {\n observer.next(value);\n }\n }\n });\n }\n\n error(err: any) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.hasError = this.isStopped = true;\n this.thrownError = err;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.error(err);\n }\n }\n });\n }\n\n complete() {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.isStopped = true;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.complete();\n }\n }\n });\n }\n\n unsubscribe() {\n this.isStopped = this.closed = true;\n this.observers = this.currentObservers = null!;\n }\n\n get observed() {\n return this.observers?.length > 0;\n }\n\n /** @internal */\n protected _trySubscribe(subscriber: Subscriber): TeardownLogic {\n this._throwIfClosed();\n return super._trySubscribe(subscriber);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n }\n\n /** @internal */\n protected _innerSubscribe(subscriber: Subscriber) {\n const { hasError, isStopped, observers } = this;\n if (hasError || isStopped) {\n return EMPTY_SUBSCRIPTION;\n }\n this.currentObservers = null;\n observers.push(subscriber);\n return new Subscription(() => {\n this.currentObservers = null;\n arrRemove(observers, subscriber);\n });\n }\n\n /** @internal */\n protected _checkFinalizedStatuses(subscriber: Subscriber) {\n const { hasError, thrownError, isStopped } = this;\n if (hasError) {\n subscriber.error(thrownError);\n } else if (isStopped) {\n subscriber.complete();\n }\n }\n\n /**\n * Creates a new Observable with this Subject as the source. You can do this\n * to create custom Observer-side logic of the Subject and conceal it from\n * code that uses the Observable.\n * @return {Observable} Observable that the Subject casts to\n */\n asObservable(): Observable {\n const observable: any = new Observable();\n observable.source = this;\n return observable;\n }\n}\n\n/**\n * @class AnonymousSubject\n */\nexport class AnonymousSubject extends Subject {\n constructor(\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n public destination?: Observer,\n source?: Observable\n ) {\n super();\n this.source = source;\n }\n\n next(value: T) {\n this.destination?.next?.(value);\n }\n\n error(err: any) {\n this.destination?.error?.(err);\n }\n\n complete() {\n this.destination?.complete?.();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n return this.source?.subscribe(subscriber) ?? EMPTY_SUBSCRIPTION;\n }\n}\n", "import { Subject } from './Subject';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\n\n/**\n * A variant of Subject that requires an initial value and emits its current\n * value whenever it is subscribed to.\n *\n * @class BehaviorSubject\n */\nexport class BehaviorSubject extends Subject {\n constructor(private _value: T) {\n super();\n }\n\n get value(): T {\n return this.getValue();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n const subscription = super._subscribe(subscriber);\n !subscription.closed && subscriber.next(this._value);\n return subscription;\n }\n\n getValue(): T {\n const { hasError, thrownError, _value } = this;\n if (hasError) {\n throw thrownError;\n }\n this._throwIfClosed();\n return _value;\n }\n\n next(value: T): void {\n super.next((this._value = value));\n }\n}\n", "import { TimestampProvider } from '../types';\n\ninterface DateTimestampProvider extends TimestampProvider {\n delegate: TimestampProvider | undefined;\n}\n\nexport const dateTimestampProvider: DateTimestampProvider = {\n now() {\n // Use the variable rather than `this` so that the function can be called\n // without being bound to the provider.\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n", "import { Subject } from './Subject';\nimport { TimestampProvider } from './types';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * A variant of {@link Subject} that \"replays\" old values to new subscribers by emitting them when they first subscribe.\n *\n * `ReplaySubject` has an internal buffer that will store a specified number of values that it has observed. Like `Subject`,\n * `ReplaySubject` \"observes\" values by having them passed to its `next` method. When it observes a value, it will store that\n * value for a time determined by the configuration of the `ReplaySubject`, as passed to its constructor.\n *\n * When a new subscriber subscribes to the `ReplaySubject` instance, it will synchronously emit all values in its buffer in\n * a First-In-First-Out (FIFO) manner. The `ReplaySubject` will also complete, if it has observed completion; and it will\n * error if it has observed an error.\n *\n * There are two main configuration items to be concerned with:\n *\n * 1. `bufferSize` - This will determine how many items are stored in the buffer, defaults to infinite.\n * 2. `windowTime` - The amount of time to hold a value in the buffer before removing it from the buffer.\n *\n * Both configurations may exist simultaneously. So if you would like to buffer a maximum of 3 values, as long as the values\n * are less than 2 seconds old, you could do so with a `new ReplaySubject(3, 2000)`.\n *\n * ### Differences with BehaviorSubject\n *\n * `BehaviorSubject` is similar to `new ReplaySubject(1)`, with a couple of exceptions:\n *\n * 1. `BehaviorSubject` comes \"primed\" with a single value upon construction.\n * 2. `ReplaySubject` will replay values, even after observing an error, where `BehaviorSubject` will not.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n * @see {@link shareReplay}\n */\nexport class ReplaySubject extends Subject {\n private _buffer: (T | number)[] = [];\n private _infiniteTimeWindow = true;\n\n /**\n * @param bufferSize The size of the buffer to replay on subscription\n * @param windowTime The amount of time the buffered items will stay buffered\n * @param timestampProvider An object with a `now()` method that provides the current timestamp. This is used to\n * calculate the amount of time something has been buffered.\n */\n constructor(\n private _bufferSize = Infinity,\n private _windowTime = Infinity,\n private _timestampProvider: TimestampProvider = dateTimestampProvider\n ) {\n super();\n this._infiniteTimeWindow = _windowTime === Infinity;\n this._bufferSize = Math.max(1, _bufferSize);\n this._windowTime = Math.max(1, _windowTime);\n }\n\n next(value: T): void {\n const { isStopped, _buffer, _infiniteTimeWindow, _timestampProvider, _windowTime } = this;\n if (!isStopped) {\n _buffer.push(value);\n !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);\n }\n this._trimBuffer();\n super.next(value);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._trimBuffer();\n\n const subscription = this._innerSubscribe(subscriber);\n\n const { _infiniteTimeWindow, _buffer } = this;\n // We use a copy here, so reentrant code does not mutate our array while we're\n // emitting it to a new subscriber.\n const copy = _buffer.slice();\n for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i] as T);\n }\n\n this._checkFinalizedStatuses(subscriber);\n\n return subscription;\n }\n\n private _trimBuffer() {\n const { _bufferSize, _timestampProvider, _buffer, _infiniteTimeWindow } = this;\n // If we don't have an infinite buffer size, and we're over the length,\n // use splice to truncate the old buffer values off. Note that we have to\n // double the size for instances where we're not using an infinite time window\n // because we're storing the values and the timestamps in the same array.\n const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;\n _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);\n\n // Now, if we're not in an infinite time window, remove all values where the time is\n // older than what is allowed.\n if (!_infiniteTimeWindow) {\n const now = _timestampProvider.now();\n let last = 0;\n // Search the array for the first timestamp that isn't expired and\n // truncate the buffer up to that point.\n for (let i = 1; i < _buffer.length && (_buffer[i] as number) <= now; i += 2) {\n last = i;\n }\n last && _buffer.splice(0, last + 1);\n }\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Subscription } from '../Subscription';\nimport { SchedulerAction } from '../types';\n\n/**\n * A unit of work to be executed in a `scheduler`. An action is typically\n * created from within a {@link SchedulerLike} and an RxJS user does not need to concern\n * themselves about creating and manipulating an Action.\n *\n * ```ts\n * class Action extends Subscription {\n * new (scheduler: Scheduler, work: (state?: T) => void);\n * schedule(state?: T, delay: number = 0): Subscription;\n * }\n * ```\n *\n * @class Action\n */\nexport class Action extends Subscription {\n constructor(scheduler: Scheduler, work: (this: SchedulerAction, state?: T) => void) {\n super();\n }\n /**\n * Schedules this action on its parent {@link SchedulerLike} for execution. May be passed\n * some context object, `state`. May happen at some point in the future,\n * according to the `delay` parameter, if specified.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler.\n * @return {void}\n */\n public schedule(state?: T, delay: number = 0): Subscription {\n return this;\n }\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetIntervalFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearIntervalFunction = (handle: TimerHandle) => void;\n\ninterface IntervalProvider {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n delegate:\n | {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n }\n | undefined;\n}\n\nexport const intervalProvider: IntervalProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setInterval(handler: () => void, timeout?: number, ...args) {\n const { delegate } = intervalProvider;\n if (delegate?.setInterval) {\n return delegate.setInterval(handler, timeout, ...args);\n }\n return setInterval(handler, timeout, ...args);\n },\n clearInterval(handle) {\n const { delegate } = intervalProvider;\n return (delegate?.clearInterval || clearInterval)(handle as any);\n },\n delegate: undefined,\n};\n", "import { Action } from './Action';\nimport { SchedulerAction } from '../types';\nimport { Subscription } from '../Subscription';\nimport { AsyncScheduler } from './AsyncScheduler';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncAction extends Action {\n public id: TimerHandle | undefined;\n public state?: T;\n // @ts-ignore: Property has no initializer and is not definitely assigned\n public delay: number;\n protected pending: boolean = false;\n\n constructor(protected scheduler: AsyncScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (this.closed) {\n return this;\n }\n\n // Always replace the current state with the new state.\n this.state = state;\n\n const id = this.id;\n const scheduler = this.scheduler;\n\n //\n // Important implementation note:\n //\n // Actions only execute once by default, unless rescheduled from within the\n // scheduled callback. This allows us to implement single and repeat\n // actions via the same code path, without adding API surface area, as well\n // as mimic traditional recursion but across asynchronous boundaries.\n //\n // However, JS runtimes and timers distinguish between intervals achieved by\n // serial `setTimeout` calls vs. a single `setInterval` call. An interval of\n // serial `setTimeout` calls can be individually delayed, which delays\n // scheduling the next `setTimeout`, and so on. `setInterval` attempts to\n // guarantee the interval callback will be invoked more precisely to the\n // interval period, regardless of load.\n //\n // Therefore, we use `setInterval` to schedule single and repeat actions.\n // If the action reschedules itself with the same delay, the interval is not\n // canceled. If the action doesn't reschedule, or reschedules with a\n // different delay, the interval will be canceled after scheduled callback\n // execution.\n //\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n\n // Set the pending flag indicating that this action has been scheduled, or\n // has recursively rescheduled itself.\n this.pending = true;\n\n this.delay = delay;\n // If this action has already an async Id, don't request a new one.\n this.id = this.id ?? this.requestAsyncId(scheduler, this.id, delay);\n\n return this;\n }\n\n protected requestAsyncId(scheduler: AsyncScheduler, _id?: TimerHandle, delay: number = 0): TimerHandle {\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n }\n\n protected recycleAsyncId(_scheduler: AsyncScheduler, id?: TimerHandle, delay: number | null = 0): TimerHandle | undefined {\n // If this action is rescheduled with the same delay time, don't clear the interval id.\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n // Otherwise, if the action's delay time is different from the current delay,\n // or the action has been rescheduled before it's executed, clear the interval id\n if (id != null) {\n intervalProvider.clearInterval(id);\n }\n\n return undefined;\n }\n\n /**\n * Immediately executes this action and the `work` it contains.\n * @return {any}\n */\n public execute(state: T, delay: number): any {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n\n this.pending = false;\n const error = this._execute(state, delay);\n if (error) {\n return error;\n } else if (this.pending === false && this.id != null) {\n // Dequeue if the action didn't reschedule itself. Don't call\n // unsubscribe(), because the action could reschedule later.\n // For example:\n // ```\n // scheduler.schedule(function doWork(counter) {\n // /* ... I'm a busy worker bee ... */\n // var originalAction = this;\n // /* wait 100ms before rescheduling the action */\n // setTimeout(function () {\n // originalAction.schedule(counter + 1);\n // }, 100);\n // }, 1000);\n // ```\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n }\n\n protected _execute(state: T, _delay: number): any {\n let errored: boolean = false;\n let errorValue: any;\n try {\n this.work(state);\n } catch (e) {\n errored = true;\n // HACK: Since code elsewhere is relying on the \"truthiness\" of the\n // return here, we can't have it return \"\" or 0 or false.\n // TODO: Clean this up when we refactor schedulers mid-version-8 or so.\n errorValue = e ? e : new Error('Scheduled action threw falsy error');\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n }\n\n unsubscribe() {\n if (!this.closed) {\n const { id, scheduler } = this;\n const { actions } = scheduler;\n\n this.work = this.state = this.scheduler = null!;\n this.pending = false;\n\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n\n this.delay = null!;\n super.unsubscribe();\n }\n }\n}\n", "import { Action } from './scheduler/Action';\nimport { Subscription } from './Subscription';\nimport { SchedulerLike, SchedulerAction } from './types';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * An execution context and a data structure to order tasks and schedule their\n * execution. Provides a notion of (potentially virtual) time, through the\n * `now()` getter method.\n *\n * Each unit of work in a Scheduler is called an `Action`.\n *\n * ```ts\n * class Scheduler {\n * now(): number;\n * schedule(work, delay?, state?): Subscription;\n * }\n * ```\n *\n * @class Scheduler\n * @deprecated Scheduler is an internal implementation detail of RxJS, and\n * should not be used directly. Rather, create your own class and implement\n * {@link SchedulerLike}. Will be made internal in v8.\n */\nexport class Scheduler implements SchedulerLike {\n public static now: () => number = dateTimestampProvider.now;\n\n constructor(private schedulerActionCtor: typeof Action, now: () => number = Scheduler.now) {\n this.now = now;\n }\n\n /**\n * A getter method that returns a number representing the current time\n * (at the time this function was called) according to the scheduler's own\n * internal clock.\n * @return {number} A number that represents the current time. May or may not\n * have a relation to wall-clock time. May or may not refer to a time unit\n * (e.g. milliseconds).\n */\n public now: () => number;\n\n /**\n * Schedules a function, `work`, for execution. May happen at some point in\n * the future, according to the `delay` parameter, if specified. May be passed\n * some context object, `state`, which will be passed to the `work` function.\n *\n * The given arguments will be processed an stored as an Action object in a\n * queue of actions.\n *\n * @param {function(state: ?T): ?Subscription} work A function representing a\n * task, or some unit of work to be executed by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler itself.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @return {Subscription} A subscription in order to be able to unsubscribe\n * the scheduled work.\n */\n public schedule(work: (this: SchedulerAction, state?: T) => void, delay: number = 0, state?: T): Subscription {\n return new this.schedulerActionCtor(this, work).schedule(state, delay);\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Action } from './Action';\nimport { AsyncAction } from './AsyncAction';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncScheduler extends Scheduler {\n public actions: Array> = [];\n /**\n * A flag to indicate whether the Scheduler is currently executing a batch of\n * queued actions.\n * @type {boolean}\n * @internal\n */\n public _active: boolean = false;\n /**\n * An internal ID used to track the latest asynchronous task such as those\n * coming from `setTimeout`, `setInterval`, `requestAnimationFrame`, and\n * others.\n * @type {any}\n * @internal\n */\n public _scheduled: TimerHandle | undefined;\n\n constructor(SchedulerAction: typeof Action, now: () => number = Scheduler.now) {\n super(SchedulerAction, now);\n }\n\n public flush(action: AsyncAction): void {\n const { actions } = this;\n\n if (this._active) {\n actions.push(action);\n return;\n }\n\n let error: any;\n this._active = true;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions.shift()!)); // exhaust the scheduler queue\n\n this._active = false;\n\n if (error) {\n while ((action = actions.shift()!)) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\n/**\n *\n * Async Scheduler\n *\n * Schedule task as if you used setTimeout(task, duration)\n *\n * `async` scheduler schedules tasks asynchronously, by putting them on the JavaScript\n * event loop queue. It is best used to delay tasks in time or to schedule tasks repeating\n * in intervals.\n *\n * If you just want to \"defer\" task, that is to perform it right after currently\n * executing synchronous code ends (commonly achieved by `setTimeout(deferredTask, 0)`),\n * better choice will be the {@link asapScheduler} scheduler.\n *\n * ## Examples\n * Use async scheduler to delay task\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * const task = () => console.log('it works!');\n *\n * asyncScheduler.schedule(task, 2000);\n *\n * // After 2 seconds logs:\n * // \"it works!\"\n * ```\n *\n * Use async scheduler to repeat task in intervals\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * function task(state) {\n * console.log(state);\n * this.schedule(state + 1, 1000); // `this` references currently executing Action,\n * // which we reschedule with new state and delay\n * }\n *\n * asyncScheduler.schedule(task, 3000, 0);\n *\n * // Logs:\n * // 0 after 3s\n * // 1 after 4s\n * // 2 after 5s\n * // 3 after 6s\n * ```\n */\n\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\n\n/**\n * @deprecated Renamed to {@link asyncScheduler}. Will be removed in v8.\n */\nexport const async = asyncScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { Subscription } from '../Subscription';\nimport { QueueScheduler } from './QueueScheduler';\nimport { SchedulerAction } from '../types';\nimport { TimerHandle } from './timerHandle';\n\nexport class QueueAction extends AsyncAction {\n constructor(protected scheduler: QueueScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (delay > 0) {\n return super.schedule(state, delay);\n }\n this.delay = delay;\n this.state = state;\n this.scheduler.flush(this);\n return this;\n }\n\n public execute(state: T, delay: number): any {\n return delay > 0 || this.closed ? super.execute(state, delay) : this._execute(state, delay);\n }\n\n protected requestAsyncId(scheduler: QueueScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n\n if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n\n // Otherwise flush the scheduler starting with this action.\n scheduler.flush(this);\n\n // HACK: In the past, this was returning `void`. However, `void` isn't a valid\n // `TimerHandle`, and generally the return value here isn't really used. So the\n // compromise is to return `0` which is both \"falsy\" and a valid `TimerHandle`,\n // as opposed to refactoring every other instanceo of `requestAsyncId`.\n return 0;\n }\n}\n", "import { AsyncScheduler } from './AsyncScheduler';\n\nexport class QueueScheduler extends AsyncScheduler {\n}\n", "import { QueueAction } from './QueueAction';\nimport { QueueScheduler } from './QueueScheduler';\n\n/**\n *\n * Queue Scheduler\n *\n * Put every next task on a queue, instead of executing it immediately\n *\n * `queue` scheduler, when used with delay, behaves the same as {@link asyncScheduler} scheduler.\n *\n * When used without delay, it schedules given task synchronously - executes it right when\n * it is scheduled. However when called recursively, that is when inside the scheduled task,\n * another task is scheduled with queue scheduler, instead of executing immediately as well,\n * that task will be put on a queue and wait for current one to finish.\n *\n * This means that when you execute task with `queue` scheduler, you are sure it will end\n * before any other task scheduled with that scheduler will start.\n *\n * ## Examples\n * Schedule recursively first, then do something\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(() => {\n * queueScheduler.schedule(() => console.log('second')); // will not happen now, but will be put on a queue\n *\n * console.log('first');\n * });\n *\n * // Logs:\n * // \"first\"\n * // \"second\"\n * ```\n *\n * Reschedule itself recursively\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(function(state) {\n * if (state !== 0) {\n * console.log('before', state);\n * this.schedule(state - 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * console.log('after', state);\n * }\n * }, 0, 3);\n *\n * // In scheduler that runs recursively, you would expect:\n * // \"before\", 3\n * // \"before\", 2\n * // \"before\", 1\n * // \"after\", 1\n * // \"after\", 2\n * // \"after\", 3\n *\n * // But with queue it logs:\n * // \"before\", 3\n * // \"after\", 3\n * // \"before\", 2\n * // \"after\", 2\n * // \"before\", 1\n * // \"after\", 1\n * ```\n */\n\nexport const queueScheduler = new QueueScheduler(QueueAction);\n\n/**\n * @deprecated Renamed to {@link queueScheduler}. Will be removed in v8.\n */\nexport const queue = queueScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\nimport { SchedulerAction } from '../types';\nimport { animationFrameProvider } from './animationFrameProvider';\nimport { TimerHandle } from './timerHandle';\n\nexport class AnimationFrameAction extends AsyncAction {\n constructor(protected scheduler: AnimationFrameScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n protected requestAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay is greater than 0, request as an async action.\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n // Push the action to the end of the scheduler queue.\n scheduler.actions.push(this);\n // If an animation frame has already been requested, don't request another\n // one. If an animation frame hasn't been requested yet, request one. Return\n // the current animation frame request id.\n return scheduler._scheduled || (scheduler._scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n }\n\n protected recycleAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n if (delay != null ? delay > 0 : this.delay > 0) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n // If the scheduler queue has no remaining actions with the same async id,\n // cancel the requested animation frame and set the scheduled flag to\n // undefined so the next AnimationFrameAction will request its own.\n const { actions } = scheduler;\n if (id != null && actions[actions.length - 1]?.id !== id) {\n animationFrameProvider.cancelAnimationFrame(id as number);\n scheduler._scheduled = undefined;\n }\n // Return undefined so the action knows to request a new async id if it's rescheduled.\n return undefined;\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\nexport class AnimationFrameScheduler extends AsyncScheduler {\n public flush(action?: AsyncAction): void {\n this._active = true;\n // The async id that effects a call to flush is stored in _scheduled.\n // Before executing an action, it's necessary to check the action's async\n // id to determine whether it's supposed to be executed in the current\n // flush.\n // Previous implementations of this method used a count to determine this,\n // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n // are removed from the actions array and that can shift actions that are\n // scheduled to be executed in a subsequent flush into positions at which\n // they are executed within the current flush.\n const flushId = this._scheduled;\n this._scheduled = undefined;\n\n const { actions } = this;\n let error: any;\n action = action || actions.shift()!;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n this._active = false;\n\n if (error) {\n while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AnimationFrameAction } from './AnimationFrameAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\n\n/**\n *\n * Animation Frame Scheduler\n *\n * Perform task when `window.requestAnimationFrame` would fire\n *\n * When `animationFrame` scheduler is used with delay, it will fall back to {@link asyncScheduler} scheduler\n * behaviour.\n *\n * Without delay, `animationFrame` scheduler can be used to create smooth browser animations.\n * It makes sure scheduled task will happen just before next browser content repaint,\n * thus performing animations as efficiently as possible.\n *\n * ## Example\n * Schedule div height animation\n * ```ts\n * // html:
\n * import { animationFrameScheduler } from 'rxjs';\n *\n * const div = document.querySelector('div');\n *\n * animationFrameScheduler.schedule(function(height) {\n * div.style.height = height + \"px\";\n *\n * this.schedule(height + 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * }, 0, 0);\n *\n * // You will see a div element growing in height\n * ```\n */\n\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\n\n/**\n * @deprecated Renamed to {@link animationFrameScheduler}. Will be removed in v8.\n */\nexport const animationFrame = animationFrameScheduler;\n", "import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\n\n/**\n * A simple Observable that emits no items to the Observer and immediately\n * emits a complete notification.\n *\n * Just emits 'complete', and nothing else.\n *\n * ![](empty.png)\n *\n * A simple Observable that only emits the complete notification. It can be used\n * for composing with other Observables, such as in a {@link mergeMap}.\n *\n * ## Examples\n *\n * Log complete notification\n *\n * ```ts\n * import { EMPTY } from 'rxjs';\n *\n * EMPTY.subscribe({\n * next: () => console.log('Next'),\n * complete: () => console.log('Complete!')\n * });\n *\n * // Outputs\n * // Complete!\n * ```\n *\n * Emit the number 7, then complete\n *\n * ```ts\n * import { EMPTY, startWith } from 'rxjs';\n *\n * const result = EMPTY.pipe(startWith(7));\n * result.subscribe(x => console.log(x));\n *\n * // Outputs\n * // 7\n * ```\n *\n * Map and flatten only odd numbers to the sequence `'a'`, `'b'`, `'c'`\n *\n * ```ts\n * import { interval, mergeMap, of, EMPTY } from 'rxjs';\n *\n * const interval$ = interval(1000);\n * const result = interval$.pipe(\n * mergeMap(x => x % 2 === 1 ? of('a', 'b', 'c') : EMPTY),\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following to the console:\n * // x is equal to the count on the interval, e.g. (0, 1, 2, 3, ...)\n * // x will occur every 1000ms\n * // if x % 2 is equal to 1, print a, b, c (each on its own)\n * // if x % 2 is not equal to 1, nothing will be output\n * ```\n *\n * @see {@link Observable}\n * @see {@link NEVER}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const EMPTY = new Observable((subscriber) => subscriber.complete());\n\n/**\n * @param scheduler A {@link SchedulerLike} to use for scheduling\n * the emission of the complete notification.\n * @deprecated Replaced with the {@link EMPTY} constant or {@link scheduled} (e.g. `scheduled([], scheduler)`). Will be removed in v8.\n */\nexport function empty(scheduler?: SchedulerLike) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\n\nfunction emptyScheduled(scheduler: SchedulerLike) {\n return new Observable((subscriber) => scheduler.schedule(() => subscriber.complete()));\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport function isScheduler(value: any): value is SchedulerLike {\n return value && isFunction(value.schedule);\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\n\nfunction last(arr: T[]): T | undefined {\n return arr[arr.length - 1];\n}\n\nexport function popResultSelector(args: any[]): ((...args: unknown[]) => unknown) | undefined {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\n\nexport function popScheduler(args: any[]): SchedulerLike | undefined {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\n\nexport function popNumber(args: any[], defaultValue: number): number {\n return typeof last(args) === 'number' ? args.pop()! : defaultValue;\n}\n", "export const isArrayLike = ((x: any): x is ArrayLike => x && typeof x.length === 'number' && typeof x !== 'function');", "import { isFunction } from \"./isFunction\";\n\n/**\n * Tests to see if the object is \"thennable\".\n * @param value the object to test\n */\nexport function isPromise(value: any): value is PromiseLike {\n return isFunction(value?.then);\n}\n", "import { InteropObservable } from '../types';\nimport { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being Observable (but not necessary an Rx Observable) */\nexport function isInteropObservable(input: any): input is InteropObservable {\n return isFunction(input[Symbol_observable]);\n}\n", "import { isFunction } from './isFunction';\n\nexport function isAsyncIterable(obj: any): obj is AsyncIterable {\n return Symbol.asyncIterator && isFunction(obj?.[Symbol.asyncIterator]);\n}\n", "/**\n * Creates the TypeError to throw if an invalid object is passed to `from` or `scheduled`.\n * @param input The object that was passed.\n */\nexport function createInvalidObservableTypeError(input: any) {\n // TODO: We should create error codes that can be looked up, so this can be less verbose.\n return new TypeError(\n `You provided ${\n input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`\n } where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`\n );\n}\n", "export function getSymbolIterator(): symbol {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator' as any;\n }\n\n return Symbol.iterator;\n}\n\nexport const iterator = getSymbolIterator();\n", "import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being an Iterable */\nexport function isIterable(input: any): input is Iterable {\n return isFunction(input?.[Symbol_iterator]);\n}\n", "import { ReadableStreamLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport async function* readableStreamLikeToAsyncGenerator(readableStream: ReadableStreamLike): AsyncGenerator {\n const reader = readableStream.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n return;\n }\n yield value!;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nexport function isReadableStreamLike(obj: any): obj is ReadableStreamLike {\n // We don't want to use instanceof checks because they would return\n // false for instances from another Realm, like an + +
+

Example: +

autoRetrieveWhenPull:
+  - CustomApplication:MyCustomApplication
+  - CustomApplication:MyOtherCustomApplication
+  - CustomApplication:MyThirdCustomApp
+

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
debug
-d
booleanActivate debug mode (more logs)
flags-diroptionundefined
jsonbooleanFormat output as json.
skipauthbooleanSkip authentication check when a default username is required
target-org
-o
optionundefined
websocketoptionWebsocket host:port for VsCode SFDX Hardis UI integration
+

Examples

+
$ sf hardis:scratch:pull
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hardis/scratch/push/index.html b/hardis/scratch/push/index.html new file mode 100644 index 000000000..6f35085cb --- /dev/null +++ b/hardis/scratch/push/index.html @@ -0,0 +1,7802 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + push - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

hardis:scratch:push

+

Description

+

Push local files to scratch org

+

Calls sf project deploy start under the hood

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
debug
-d
booleanActivate debug mode (more logs)
flags-diroptionundefined
jsonbooleanFormat output as json.
skipauthbooleanSkip authentication check when a default username is required
target-org
-o
optionundefined
websocketoptionWebsocket host:port for VsCode SFDX Hardis UI integration
+

Examples

+
$ sf hardis:scratch:push
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hardis/source/deploy/index.html b/hardis/source/deploy/index.html new file mode 100644 index 000000000..3d4aa4b9e --- /dev/null +++ b/hardis/source/deploy/index.html @@ -0,0 +1,8048 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + deploy - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

hardis:source:deploy

+

Description

+

sfdx-hardis wrapper for sfdx force:source:deploy that displays tips to solve deployment errors.

+

Additional to the base command wrapper: If using --checkonly, add options --checkcoverage and --coverageformatters json-summary to check that org coverage is > 75% (or value defined in .sfdx-hardis.yml property apexTestsMinCoverageOrgWide)

+

Deployment results

+

You can also have deployment results as pull request comments, on:

+ +

Assisted solving of Salesforce deployments errors

+

Deployment pre or post commands

+

You can define command lines to run before or after a deployment, with parameters:

+
    +
  • id: Unique Id for the command
  • +
  • label: Human readable label for the command
  • +
  • skipIfError: If defined to "true", the post-command won't be run if there is a deployment failure
  • +
  • context: Defines the context where the command will be run. Can be all (default), check-deployment-only or process-deployment-only
  • +
  • runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)
  • +
+

If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

+

Example:

+
commandsPreDeploy:
+  - id: knowledgeUnassign
+    label: Remove KnowledgeUser right to the user who has it
+    command: sf data update record --sobject User --where "UserPermissionsKnowledgeUser='true'" --values "UserPermissionsKnowledgeUser='false'" --json
+  - id: knowledgeAssign
+    label: Assign Knowledge user to the deployment user
+    command: sf data update record --sobject User --where "Username='deploy.github@myclient.com'" --values "UserPermissionsKnowledgeUser='true'" --json
+
+commandsPostDeploy:
+  - id: knowledgeUnassign
+    label: Remove KnowledgeUser right to the user who has it
+    command: sf data update record --sobject User --where "UserPermissionsKnowledgeUser='true'" --values "UserPermissionsKnowledgeUser='false'" --json
+  - id: knowledgeAssign
+    label: Assign Knowledge user to desired username
+    command: sf data update record --sobject User --where "Username='admin-yser@myclient.com'" --values "UserPermissionsKnowledgeUser='true'" --json
+  - id: someActionToRunJustOneTime
+    label: And to run only if deployment is success
+    command: sf sfdmu:run ...
+    skipIfError: true
+    context: process-deployment-only
+    runOnlyOnceByOrg: true
+
+

Notes:

+
    +
  • You can disable coloring of errors in red by defining env variable SFDX_HARDIS_DEPLOY_ERR_COLORS=false
  • +
+

See documentation of Salesforce command

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
checkcoveragebooleanCheck Apex org coverage
checkonly
-c
booleancheckonly
coverageformattersoptioncoverageformatters
debugbooleandebug
flags-diroptionundefined
forceoverwrite
-f
booleanforceoverwrite
ignoreerrorsbooleanignoreErrors
ignorewarnings
-g
booleanignoreWarnings
jsonbooleanFormat output as json.
junitbooleanjunit
manifest
-x
optionflagsLong.manifest
metadata
-m
optionmetadata
postdestructivechangesoptionpostdestructivechanges
predestructivechangesoptionpredestructivechanges
resultsdiroptionresultsdir
runtests
-r
optionrunTests
soapdeploybooleansoapDeploy
sourcepath
-p
optionsourcePath
target-org
-o
optionundefined
testlevel
-l
optiontestlevelNoTestRunNoTestRun
RunSpecifiedTests
RunLocalTests
RunAllTestsInOrg
tracksource
-t
booleantracksource
validateddeployrequestid
-q
optionvalidateDeployRequestId
verbosebooleanverbose
wait
-w
optionwait60
websocketoptionwebsocket
+

Examples

+
$ sf hardis:source:deploy -x manifest/package.xml --wait 60 --ignorewarnings --testlevel RunLocalTests --postdestructivechanges ./manifest/destructiveChanges.xml --target-org nicolas.vuillamy@cloudity.com.sfdxhardis --checkonly --checkcoverage --verbose --coverageformatters json-summary
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hardis/source/push/index.html b/hardis/source/push/index.html new file mode 100644 index 000000000..d677963ac --- /dev/null +++ b/hardis/source/push/index.html @@ -0,0 +1,7825 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + push - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

hardis:source:push

+

Description

+

sfdx-hardis wrapper for sfdx force:source:push that displays tips to solve deployment errors.

+

Assisted solving of Salesforce deployments errors

+

See documentation of Salesforce command

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
debugbooleandebug
flags-diroptionundefined
forceoverwrite
-f
booleanforceoverwrite
ignorewarnings
-g
booleanignorewarnings
jsonbooleanFormat output as json.
quietbooleanquiet
target-org
-o
optionundefined
wait
-w
optionwait60
websocketoptionwebsocket
+

Examples

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hardis/source/retrieve/index.html b/hardis/source/retrieve/index.html new file mode 100644 index 000000000..cb1177ce6 --- /dev/null +++ b/hardis/source/retrieve/index.html @@ -0,0 +1,7876 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + retrieve - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

hardis:source:retrieve

+

Description

+

sfdx-hardis wrapper for sfdx force:source:retrieve

+
    +
  • If no retrieve constraint is sent, as assisted menu will request the list of metadatas to retrieve
  • +
  • If no org is selected , an assisted menu will request the user to choose one
  • +
+

See documentation of Salesforce command

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
apiversion
-a
optionOverride the api version used for api requests made by this command
debug
-d
booleandebugMode
flags-diroptionundefined
forceoverwrite
-f
booleanforceoverwrite
jsonbooleanFormat output as json.
manifest
-x
optionmanifest
metadata
-m
optionmetadata
packagenames
-n
optionpackagenames
skipauthbooleanSkip authentication check when a default username is required
sourcepath
-p
optionsourcePath
target-org
-o
optionundefined
tracksource
-t
booleantracksource
verbosebooleanverbose
wait
-w
optionwait
websocketoptionwebsocket
+

Examples

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hardis/work/new/index.html b/hardis/work/new/index.html new file mode 100644 index 000000000..9140b7eb3 --- /dev/null +++ b/hardis/work/new/index.html @@ -0,0 +1,7837 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + new - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

hardis:work:new

+

Description

+

Assisted menu to start working on a Salesforce task.

+

Advanced instructions in Create New Task documentation

+

At the end of the command, it will allow you to work on either a scratch org or a sandbox, depending on your choices.

+

Under the hood, it can:

+
    +
  • Make git pull to be up to date with target branch
  • +
  • Create new git branch with formatted name (you can override the choices using .sfdx-hardis.yml property branchPrefixChoices)
  • +
  • Create and initialize a scratch org or a source-tracked sandbox (config can be defined using config/.sfdx-hardis.yml):
  • +
  • (and for scratch org only for now):
      +
    • Install packages + - Use property installedPackages
        +
      • Push sources
      • +
      • Assign permission sets
          +
        • Use property initPermissionSets
        • +
        +
      • +
      • Run apex initialization scripts
          +
        • Use property scratchOrgInitApexScripts
        • +
        +
      • +
      • Load data
          +
        • Use property dataPackages
        • +
        +
      • +
      +
    • +
    +
  • +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
debug
-d
booleanActivate debug mode (more logs)
flags-diroptionundefined
jsonbooleanFormat output as json.
skipauthbooleanSkip authentication check when a default username is required
target-dev-hub
-v
optionundefined
target-org
-o
optionundefined
websocketoptionWebsocket host:port for VsCode SFDX Hardis UI integration
+

Examples

+
$ sf hardis:work:task:new
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hardis/work/refresh/index.html b/hardis/work/refresh/index.html new file mode 100644 index 000000000..fdf289f95 --- /dev/null +++ b/hardis/work/refresh/index.html @@ -0,0 +1,7809 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + refresh - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

hardis:work:refresh

+

Description

+

Make my local branch and my scratch org up to date with the most recent sources

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
debug
-d
booleanActivate debug mode (more logs)
flags-diroptionundefined
jsonbooleanFormat output as json.
nopull
-n
booleanNo scratch pull before save (careful if you use that!)
skipauthbooleanSkip authentication check when a default username is required
target-org
-o
optionundefined
websocketoptionWebsocket host:port for VsCode SFDX Hardis UI integration
+

Examples

+
$ sf hardis:work:refresh
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hardis/work/resetselection/index.html b/hardis/work/resetselection/index.html new file mode 100644 index 000000000..61c1ac1bf --- /dev/null +++ b/hardis/work/resetselection/index.html @@ -0,0 +1,7802 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + resetselection - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

hardis:work:resetselection

+

Description

+

Resets the selection that we want to add in the merge request

+

Calls a soft git reset behind the hood

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
debug
-d
booleanActivate debug mode (more logs)
flags-diroptionundefined
jsonbooleanFormat output as json.
skipauthbooleanSkip authentication check when a default username is required
target-org
-o
optionundefined
websocketoptionWebsocket host:port for VsCode SFDX Hardis UI integration
+

Examples

+
$ sf hardis:work:resetsave
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hardis/work/save/index.html b/hardis/work/save/index.html new file mode 100644 index 000000000..1d106c92a --- /dev/null +++ b/hardis/work/save/index.html @@ -0,0 +1,7874 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + save - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

hardis:work:save

+

Description

+

When a work task is completed, guide user to create a merge request

+

Advanced instructions in Publish a task

+
    +
  • Generate package-xml diff using sfdx-git-delta
  • +
  • Automatically update manifest/package.xml and manifest/destructiveChanges.xml according to the committed updates
  • +
  • Automatically Clean XML files using .sfdx-hardis.yml properties
      +
    • autocleantypes: List of auto-performed sources cleanings, available on command hardis:project:clean:references
    • +
    • autoRemoveUserPermissions: List of userPermission to automatically remove from profile metadatas
    • +
    +
  • +
+

Example:

+
autoCleanTypes:
+  - checkPermissions
+  - destructivechanges
+  - datadotcom
+  - minimizeProfiles
+  - listViewsMine
+autoRemoveUserPermissions:
+  - EnableCommunityAppLauncher
+  - FieldServiceAccess
+  - OmnichannelInventorySync
+  - SendExternalEmailAvailable
+  - UseOmnichannelInventoryAPIs
+  - ViewDataLeakageEvents
+  - ViewMLModels
+  - ViewPlatformEvents
+  - WorkCalibrationUser
+
+
    +
  • Push commit to server
  • +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
autobooleanNo user prompts (when called from CI for example)
debug
-d
booleanActivate debug mode (more logs)
flags-diroptionundefined
jsonbooleanFormat output as json.
noclean
-c
booleanNo cleaning of local sources
nogit
-g
booleanNo automated git operations
nopull
-n
booleanNo scratch pull before save
skipauthbooleanSkip authentication check when a default username is required
target-org
-o
optionundefined
targetbranchoptionName of the Merge Request target branch. Will be guessed or prompted if not provided.
websocketoptionWebsocket host:port for VsCode SFDX Hardis UI integration
+

Examples

+
$ sf hardis:work:task:save
+
+
$ sf hardis:work:task:save --nopull --nogit --noclean
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hardis/work/ws/index.html b/hardis/work/ws/index.html new file mode 100644 index 000000000..b16b0593c --- /dev/null +++ b/hardis/work/ws/index.html @@ -0,0 +1,7801 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ws - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

hardis:work:ws

+

Description

+

Technical calls to WebSocket functions

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
debug
-d
booleanActivate debug mode (more logs)
event
-e
optionWebSocket event
flags-diroptionundefined
jsonbooleanFormat output as json.
skipauthbooleanSkip authentication check when a default username is required
websocketoptionWebsocket host:port for VsCode SFDX Hardis UI integration
+

Examples

+
$ sf hardis:work:ws --event refreshStatus
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hello/world/index.html b/hello/world/index.html new file mode 100644 index 000000000..569e62224 --- /dev/null +++ b/hello/world/index.html @@ -0,0 +1,7779 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + world - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

hello:world

+

Description

+

Say hello either to the world or someone you know.

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefaultRequiredOptions
flags-diroptionundefined
jsonbooleanFormat output as json.
name
-n
optionThis person can be anyone in the world!World
+

Examples

+
Say hello to the world:
+<%= config.bin %> <%= command.id %>
+
+
Say hello to someone you know:
+<%= config.bin %> <%= command.id %> --name Astro
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 000000000..abadae1af --- /dev/null +++ b/index.html @@ -0,0 +1,9006 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + + + + +

sfdx-hardis by Cloudity Banner

+

sfdx-hardis

+

Presented at Dreamforce 23 and Dreamforce 24!

+

Version +Downloads/week +Downloads/total +Docker Pulls +GitHub stars +GitHub contributors +Mega-Linter +Secured with Trivy +License +PRs Welcome

+

Toolbox for Salesforce DX, by Cloudity & friends, natively compliant with most platforms and tools.

+

Native Integrations

+

It will allow you to:

+ +

Please see the full list of commands in Online documentation

+
+

sfdx-hardis commands are also available with UI in SFDX Hardis Visual Studio Code Extension

+

VsCode SFDX Hardis

+
+

See Dreamforce presentation

+

See Dreamforce presentation

+

Installation

+

With IDE

+

You can install Visual Studio Code extension VsCode SFDX Hardis

+

Once installed, click on Hardis Group button in VsCode left bar, and follow the additional installation instructions

+

Installation tutorial

+
+

As SFDX Plugin

+

Pre-requisites

+
    +
  • Install Node.js (recommended version)
  • +
  • Install Salesforce DX by running npm install @salesforce/cli --global command line
  • +
+

Plugin installation

+
sf plugins install sfdx-hardis
+
+

For advanced use, please also install dependencies

+
sf plugins install @salesforce/plugin-packaging
+sf plugins install sfdmu
+sf plugins install sfdx-git-delta
+sf plugins install texei-sfdx-plugin
+
+

If you are using CI/CD scripts, use echo y | sf plugins install ... to bypass prompt.

+
+

Docker

+

You can use sfdx-hardis docker images to run in CI

+ + +

See Dockerfile

+

Usage

+
sf hardis:<COMMAND> <OPTIONS>
+
+

Articles

+

Here are some articles about sfdx-hardis

+
    +
  • English
  • +
+

Conga Deployment Cheat Sheet +Questions/Answers +Salesforce Developers Podcast +sfdx-hardis: A release management tool for open-source +Assisted solving of Salesforce deployments errors +Handle Salesforce API versions Deprecation like a pro +How to mass download notes and attachments files from a Salesforce org +How to freeze / unfreeze users during a Salesforce deployment +How to detect bad words in Salesforce records using SFDX Data Loader and sfdx-hardis +Reactivate all the sandbox users with .invalid emails in 3 clicks +Invalid scope:Mine, not allowed ? Deploy your ListViews anyway !

+ +

Contributing

+

Everyone is welcome to contribute to sfdx-hardis (even juniors: we'll assist you !)

+
    +
  • Install Node.js (recommended version)
  • +
  • Install typescript by running npm install typescript --global
  • +
  • Install yarn by running npm install yarn --global
  • +
  • Install Salesforce DX by running npm install @salesforce/cli --global command line
  • +
  • Fork this repo and clone it (or just clone if you are an internal contributor)
  • +
  • At the root of the repository:
      +
    • Run yarn to install dependencies
    • +
    • Run sf plugins link to link the local sfdx-hardis to SFDX CLI
    • +
    • Run tsc --watch to transpile typescript into js everytime you update a TS file
    • +
    +
  • +
  • Debug commands using NODE_OPTIONS=--inspect-brk sf hardis:somecommand -someparameter somevalue
  • +
+

Dependencies

+

sfdx-hardis partially relies on the following SFDX Open-Source packages

+ +

Contributors

+

+ +

+

Commands

+

hardis:auth

+ + + + + + + + + + + + + +
CommandTitle
hardis:auth:login
+

hardis:cache

+ + + + + + + + + + + + + +
CommandTitle
hardis:cache:clear
+

hardis:config

+ + + + + + + + + + + + + +
CommandTitle
hardis:config:get
+

hardis:deploy

+ + + + + + + + + + + + + + + + + + + + + +
CommandTitle
hardis:deploy:quick
hardis:deploy:start
hardis:deploy:validate
+

hardis:doc

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandTitle
hardis:doc:extract:permsetgroups
hardis:doc:flow2markdown
hardis:doc:mkdocs-to-salesforce
hardis:doc:packagexml2markdown
hardis:doc:plugin:generate
hardis:doc:project2markdown
+

hardis:git

+ + + + + + + + + + + + + +
CommandTitle
hardis:git:pull-requests:extract
+

hardis:lint

+ + + + + + + + + + + + + + + + + + + + + + + + + +
CommandTitle
hardis:lint:access
hardis:lint:metadatastatus
hardis:lint:missingattributes
hardis:lint:unusedmetadatas
+

hardis:mdapi

+ + + + + + + + + + + + + +
CommandTitle
hardis:mdapi:deploy
+

hardis:misc

+ + + + + + + + + + + + + + + + + +
CommandTitle
hardis:misc:purge-references
hardis:misc:toml2csv
+

hardis:org

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandTitle
hardis:org:community:update
hardis:org:configure:data
hardis:org:configure:files
hardis:org:configure:monitoring
hardis:org:connect
hardis:org:create
hardis:org:data:delete
hardis:org:data:export
hardis:org:data:import
hardis:org:diagnose:audittrail
hardis:org:diagnose:instanceupgrade
hardis:org:diagnose:legacyapi
hardis:org:diagnose:licenses
hardis:org:diagnose:releaseupdates
hardis:org:diagnose:unused-apex-classes
hardis:org:diagnose:unused-connected-apps
hardis:org:diagnose:unusedlicenses
hardis:org:diagnose:unusedusers
hardis:org:files:export
hardis:org:files:import
hardis:org:fix:listviewmine
hardis:org:generate:packagexmlfull
hardis:org:monitor:all
hardis:org:monitor:backup
hardis:org:monitor:limits
hardis:org:multi-org-query
hardis:org:purge:apexlog
hardis:org:purge:flow
hardis:org:retrieve:packageconfig
hardis:org:retrieve:sources:analytics
hardis:org:retrieve:sources:dx
hardis:org:retrieve:sources:dx2
hardis:org:retrieve:sources:metadata
hardis:org:retrieve:sources:retrofit
hardis:org:select
hardis:org:test:apex
hardis:org:user:activateinvalid
hardis:org:user:freeze
hardis:org:user:unfreeze
+

hardis:package

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandTitle
hardis📦create
hardis📦install
hardis📦mergexml
hardis📦version:create
hardis📦version:list
hardis📦version:promote
+

hardis:packagexml

+ + + + + + + + + + + + + + + + + +
CommandTitle
hardis:packagexml:append
hardis:packagexml:remove
+

hardis:project

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandTitle
hardis:project:audit:apiversion
hardis:project:audit:callincallout
hardis:project:audit:duplicatefiles
hardis:project:audit:remotesites
hardis:project:clean:emptyitems
hardis:project:clean:filter-xml-content
hardis:project:clean:flowpositions
hardis:project:clean:hiddenitems
hardis:project:clean:listviews
hardis:project:clean:manageditems
hardis:project:clean:minimizeprofiles
hardis:project:clean:orgmissingitems
hardis:project:clean:references
hardis:project:clean:retrievefolders
hardis:project:clean:sensitive-metadatas
hardis:project:clean:standarditems
hardis:project:clean:systemdebug
hardis:project:clean:xml
hardis:project:configure:auth
hardis:project:convert:profilestopermsets
hardis:project:create
hardis:project:deploy:notify
hardis:project:deploy:quick
hardis:project:deploy:simulate
hardis:project:deploy:smart
hardis:project:deploy:sources:dx
hardis:project:deploy:sources:metadata
hardis:project:deploy:start
hardis:project:deploy:validate
hardis:project:fix:profiletabs
hardis:project:fix:v53flexipages
hardis:project:generate:flow-git-diff
hardis:project:generate:gitdelta
hardis:project:lint
hardis:project:metadata:findduplicates
+

hardis:scratch

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandTitle
hardis:scratch:create
hardis:scratch:delete
hardis:scratch:pool:create
hardis:scratch:pool:localauth
hardis:scratch:pool:refresh
hardis:scratch:pool:reset
hardis:scratch:pool:view
hardis:scratch:pull
hardis:scratch:push
+

hardis:source

+ + + + + + + + + + + + + + + + + + + + + +
CommandTitle
hardis:source:deploy
hardis:source:push
hardis:source:retrieve
+

hardis:work

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandTitle
hardis:work:new
hardis:work:refresh
hardis:work:resetselection
hardis:work:save
hardis:work:ws
+

hello:world

+ + + + + + + + + + + + + +
CommandTitle
hello:world
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascripts/gtag.js b/javascripts/gtag.js new file mode 100644 index 000000000..7ec6b3f60 --- /dev/null +++ b/javascripts/gtag.js @@ -0,0 +1,27 @@ +/* +location$.subscribe(function(url) { + window.dataLayer = window.dataLayer || []; + function gtag() { + dataLayer.push(arguments); + } + gtag("js", new Date()); + + gtag("config", "G-3DM50255LC"); +}); +*/ +var gtag_id = "G-Z1B416W4CP"; + +var script = document.createElement("script"); +script.src = "https://www.googletagmanager.com/gtag/js?id=" + gtag_id; +document.head.appendChild(script); + +location$.subscribe(function (url) { + window.dataLayer = window.dataLayer || []; + + function gtag() { + dataLayer.push(arguments); + } + + gtag("js", new Date()); + gtag("config", gtag_id); +}); diff --git a/javascripts/tables.js b/javascripts/tables.js new file mode 100644 index 000000000..513f93ec9 --- /dev/null +++ b/javascripts/tables.js @@ -0,0 +1,6 @@ +document$.subscribe(function () { + var tables = document.querySelectorAll("article table") + tables.forEach(function (table) { + new Tablesort(table) + }) +}) diff --git a/license/index.html b/license/index.html new file mode 100644 index 000000000..0302982ec --- /dev/null +++ b/license/index.html @@ -0,0 +1,8194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + License - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

License

+ +
                GNU AFFERO GENERAL PUBLIC LICENSE
+                   Version 3, 19 November 2007
+
+

Copyright (C) 2007 Free Software Foundation, Inc. https://fsf.org/ + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed.

+
                        Preamble
+
+

The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software.

+

The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users.

+

When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things.

+

Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software.

+

A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public.

+

The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version.

+

An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license.

+

The precise terms and conditions for copying, distribution and +modification follow.

+
                   TERMS AND CONDITIONS
+
+

0. Definitions.

+

"This License" refers to version 3 of the GNU Affero General Public License.

+

"Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks.

+

"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations.

+

To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work.

+

A "covered work" means either the unmodified Program or a work based +on the Program.

+

To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well.

+

To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying.

+

An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion.

+

1. Source Code.

+

The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work.

+

A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language.

+

The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it.

+

The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work.

+

The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source.

+

The Corresponding Source for a work in source code form is that +same work.

+

2. Basic Permissions.

+

All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law.

+

You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you.

+

Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary.

+

3. Protecting Users' Legal Rights From Anti-Circumvention Law.

+

No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures.

+

When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures.

+

4. Conveying Verbatim Copies.

+

You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program.

+

You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee.

+

5. Conveying Modified Source Versions.

+

You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions:

+
a) The work must carry prominent notices stating that you modified
+it, and giving a relevant date.
+
+b) The work must carry prominent notices stating that it is
+released under this License and any conditions added under section
+7.  This requirement modifies the requirement in section 4 to
+"keep intact all notices".
+
+c) You must license the entire work, as a whole, under this
+License to anyone who comes into possession of a copy.  This
+License will therefore apply, along with any applicable section 7
+additional terms, to the whole of the work, and all its parts,
+regardless of how they are packaged.  This License gives no
+permission to license the work in any other way, but it does not
+invalidate such permission if you have separately received it.
+
+d) If the work has interactive user interfaces, each must display
+Appropriate Legal Notices; however, if the Program has interactive
+interfaces that do not display Appropriate Legal Notices, your
+work need not make them do so.
+
+

A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate.

+

6. Conveying Non-Source Forms.

+

You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways:

+
a) Convey the object code in, or embodied in, a physical product
+(including a physical distribution medium), accompanied by the
+Corresponding Source fixed on a durable physical medium
+customarily used for software interchange.
+
+b) Convey the object code in, or embodied in, a physical product
+(including a physical distribution medium), accompanied by a
+written offer, valid for at least three years and valid for as
+long as you offer spare parts or customer support for that product
+model, to give anyone who possesses the object code either (1) a
+copy of the Corresponding Source for all the software in the
+product that is covered by this License, on a durable physical
+medium customarily used for software interchange, for a price no
+more than your reasonable cost of physically performing this
+conveying of source, or (2) access to copy the
+Corresponding Source from a network server at no charge.
+
+c) Convey individual copies of the object code with a copy of the
+written offer to provide the Corresponding Source.  This
+alternative is allowed only occasionally and noncommercially, and
+only if you received the object code with such an offer, in accord
+with subsection 6b.
+
+d) Convey the object code by offering access from a designated
+place (gratis or for a charge), and offer equivalent access to the
+Corresponding Source in the same way through the same place at no
+further charge.  You need not require recipients to copy the
+Corresponding Source along with the object code.  If the place to
+copy the object code is a network server, the Corresponding Source
+may be on a different server (operated by you or a third party)
+that supports equivalent copying facilities, provided you maintain
+clear directions next to the object code saying where to find the
+Corresponding Source.  Regardless of what server hosts the
+Corresponding Source, you remain obligated to ensure that it is
+available for as long as needed to satisfy these requirements.
+
+e) Convey the object code using peer-to-peer transmission, provided
+you inform other peers where the object code and Corresponding
+Source of the work are being offered to the general public at no
+charge under subsection 6d.
+
+

A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work.

+

A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product.

+

"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made.

+

If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM).

+

The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network.

+

Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying.

+

7. Additional Terms.

+

"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions.

+

When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission.

+

Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms:

+
a) Disclaiming warranty or limiting liability differently from the
+terms of sections 15 and 16 of this License; or
+
+b) Requiring preservation of specified reasonable legal notices or
+author attributions in that material or in the Appropriate Legal
+Notices displayed by works containing it; or
+
+c) Prohibiting misrepresentation of the origin of that material, or
+requiring that modified versions of such material be marked in
+reasonable ways as different from the original version; or
+
+d) Limiting the use for publicity purposes of names of licensors or
+authors of the material; or
+
+e) Declining to grant rights under trademark law for use of some
+trade names, trademarks, or service marks; or
+
+f) Requiring indemnification of licensors and authors of that
+material by anyone who conveys the material (or modified versions of
+it) with contractual assumptions of liability to the recipient, for
+any liability that these contractual assumptions directly impose on
+those licensors and authors.
+
+

All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying.

+

If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms.

+

Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way.

+

8. Termination.

+

You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11).

+

However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation.

+

Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice.

+

Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10.

+

9. Acceptance Not Required for Having Copies.

+

You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so.

+

10. Automatic Licensing of Downstream Recipients.

+

Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License.

+

An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts.

+

You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it.

+

11. Patents.

+

A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version".

+

A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License.

+

Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version.

+

In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party.

+

If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid.

+

If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it.

+

A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007.

+

Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law.

+

12. No Surrender of Others' Freedom.

+

If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program.

+

13. Remote Network Interaction; Use with the GNU General Public License.

+

Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph.

+

Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License.

+

14. Revised Versions of this License.

+

The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns.

+

Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation.

+

If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program.

+

Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version.

+

15. Disclaimer of Warranty.

+

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

+

16. Limitation of Liability.

+

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES.

+

17. Interpretation of Sections 15 and 16.

+

If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee.

+
                 END OF TERMS AND CONDITIONS
+
+        How to Apply These Terms to Your New Programs
+
+

If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms.

+

To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found.

+
<one line to give the program's name and a brief idea of what it does.>
+Copyright (C) <year>  <name of author>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published
+by the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+

Also add information on how to contact you by electronic and paper mail.

+

If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements.

+

You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +https://www.gnu.org/licenses/.

+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/overrides/main.html b/overrides/main.html new file mode 100644 index 000000000..3cf4af8cb --- /dev/null +++ b/overrides/main.html @@ -0,0 +1,4 @@ +{% extends "base.html" %} + + + diff --git a/salesforce-ai-setup/index.html b/salesforce-ai-setup/index.html new file mode 100644 index 000000000..ea0210e77 --- /dev/null +++ b/salesforce-ai-setup/index.html @@ -0,0 +1,7671 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sfdx-hardis AI assistant setup - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + +

Setup AI for sfdx-hardis

+

You need to define at least env variable OPENAI_API_KEY and make it available to your CI/CD workflow.

+

To get an OpenAi API key, create an OpenAi Platform account.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
VariableDescriptionDefault
OPENAI_API_KEYYour openai account API key
OPENAI_MODELOpenAi model used to perform prompts (see models list)gpt-4o
AI_MAXIMUM_CALL_NUMBERMaximum allowed number of calls to OpenAi API during a single sfdx-hardis command10
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-clone-repository/index.html b/salesforce-ci-cd-clone-repository/index.html new file mode 100644 index 000000000..3bf7a2c80 --- /dev/null +++ b/salesforce-ci-cd-clone-repository/index.html @@ -0,0 +1,7856 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Clone git repository of a Salesforce project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Clone the repository

+ + + + +
+

Pre-requisites

+

You need to access to a Git repository and the url of the repository to clone.

+

The release manager of the project can provide it.

+

It looks like the following: https://github.com/trailheadapps/dreamhouse-lwc.git

+
+

Clone the repository

+
+

If you don't have a folder for your git repositories, create a C:\git folder and use it as destination for your git clones !

+
+

From the Git server UI

+

Git providers UIs sometimes have a button Clone -> Open In VsCode

+

If you can use it, use it :)

+

Gitlab

+

+

If later you are prompted for username and password, you might need to create a Personal Access Token (video tuto here) and use it as password.

+

If later, it prompts several times the same password in VsCode, run the following command line

+

git config --global credential.helper store

+

Azure

+

+

From Visual Studio Code

+
    +
  • In Visual Studio Code, hit CTRL+Shirt+P then look for command Git clone then click to select it.
  • +
+

+
    +
  • Paste the url of your git repository then hit ENTER
      +
    • If you are asked for a directory and you don't have one yet, create an empty directory at the root of your hard drive, and select it (examples: C:/git or D:/git )
    • +
    +
  • +
+

+
    +
  • Click on the Open notification in VsCode
  • +
+

+ +

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-config-cleaning/index.html b/salesforce-ci-cd-config-cleaning/index.html new file mode 100644 index 000000000..e4e2b1191 --- /dev/null +++ b/salesforce-ci-cd-config-cleaning/index.html @@ -0,0 +1,7965 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure a Salesforce CI/CD Cleaning using sfdx-hardis - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Automated cleaning

+ + + + +
+

Why cleaning sources ?

+

Salesforce CI/CD Pipelines does not natively work without many manual operations to update the XML... so the deployments passes !

+

sfdx-hardis provides a set of commands to automate those boring XML updates that can be called every time a user prepares a merge request using command sf hardis:work:save

+

Here is the list of available automated cleanings, that can also be called manually using command

+

Example of cleaning config in a .sfdx-hardis.yml config file:

+
autoCleanTypes:
+  - destructivechanges
+  - datadotcom
+  - minimizeProfiles
+  - listViewsMine
+
+
+

Dashboards

+

Property: dashboards

+

Removes hardcoded user ids from Dashboards

+
+

Destructive Changes

+

Property: destructivechanges

+

Any file corresponding to an element existing in manifest/destructiveChanges.xml is deleted.

+
+

List Views Mine

+

Property: listViewsMine

+

List views with scope Mine can not be deployed.

+

As a workaround, scope is set back to Everything in XML, but the list view reference is kept in a property listViewsToSetToMine in .sfdx-hardis.yml, and after deployment, manual clicks are simulated to set back their scope to Mine !

+
+

Minimize Profiles

+

Property: minimizeProfiles

+

It is a bad practice to define on Profiles elements that can be defined on Permission Sets.

+

Salesforce will deprecate such capability in Spring 26.

+

Don't wait for that, and use minimizeProfiles cleaning to automatically remove from Profiles any permission that exists on a Permission Set !

+

The following XML tags are removed automatically:

+
    +
  • classAccesses
  • +
  • customMetadataTypeAccesses
  • +
  • externalDataSourceAccesses
  • +
  • fieldPermissions
  • +
  • objectPermissions
  • +
  • pageAccesses
  • +
  • userPermissions (except on Admin Profile)
  • +
+

You can override this list by defining a property minimizeProfilesNodesToRemove in your .sfdx-hardis.yml config file.

+

__

+

System.debug

+

Property: systemDebug

+

System.debug are useless, as explained in this article

+

Comments automatically all System.debug in the code to enhance performances.

+
+

Named metadatas

+

Cleaning can remove files related to named elements.

+

Case Entitlement

+

Property: caseentitlement

+

Removes all Case Entitlement related fields, like Case.EntitlementId and Case.MilestoneStatus

+

DataDotCom

+

Property: datadotcom

+

Removes all Case Data.com related fields, like Account.DandbCompanyId and Account.Jigsaw

+

Local Field

+

Property: localfields

+

Removes all Local fields, like Account.NameLocal and Lead.CompanyLocal

+

Product Request

+

Property: productrequest

+

Removes all Local fields, like ProductRequest.ShipToAddress and ProductRequest.ShipmentType

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-config-delta-deployment/index.html b/salesforce-ci-cd-config-delta-deployment/index.html new file mode 100644 index 000000000..e3f0fceff --- /dev/null +++ b/salesforce-ci-cd-config-delta-deployment/index.html @@ -0,0 +1,7875 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure delta deployments on a Salesforce CI/CD Project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Delta deployments

+ + + + +
+

Delta deployments

+

Full mode

+

By default, all deployments job (check deploy & process deploy) deploy the full content of the package.xml minus what is matching package-no-overwrite.xml (formerly packageDeployOnce.xml)

+

+

This is the safest way to deploy at each level

+
    +
  • major to major
  • +
  • minor to major
  • +
+
+

Delta mode

+

In order to improve performances on project with large metadata base, you can activate delta deployments for Pull Request/Merge Requests from a minor branch (examples: feature/xxx, debug/xxx) to a major branch (ex: integration, uat, preprod, production: sfdx-hardis will deploy only updated metadatas in the Pull Request / Merge Request.

+

+

+

Merge Requests / Pull Request between major branches (ex: uat to preprod) remains in full deployment mode, to avoid issues with configuration which would have been done directly in the orgs (whereas it shouldn't be, except for Reports, Dashboards and a few metadata types)

+

Examples:

+
    +
  • features/config/my-work to integration will be DELTA DEPLOYMENT
  • +
  • integration to uat will be FULL DEPLOYMENT
  • +
  • hotfixes/fix-stuff to preprod will be DELTA DEPLOYMENT
  • +
  • preprod to production will be FULL DEPLOYMENT
  • +
+
+

💡 If you want to force the use of full deployment for a PR/MR on a delta project, add "nodelta" in your latest commit title or text.

+
+
+

Configuration

+

Base

+

To activate delta deployments,you can:

+
    +
  • define useDeltaDeployment: true in config/.sfdx-hardis.yml
  • +
  • define env variable USE_DELTA_DEPLOYMENT=true
  • +
+

In case of temporary deactivation of delta deployments, you can set variable DISABLE_DELTA_DEPLOYMENT=true, it has priority on other configurations.

+
+

💡If your sfdx-hardis installation is from before 4.10.0, you might need to update your CI/CD workflows

+

Check updated versions in sfdx-hardis sources

+
+

It is recommended to use opinionated default sfdx-hardis delta deployment configuration, but if you want to tweak the config you can use the following variables:

+

Advanced

+
    +
  • USE_DELTA_DEPLOYMENT_AFTER_MERGE
      +
    • By default, after a merge sfdx-hardis will try to use QuickDeploy. If not available, it will perform a full deployment. If you want to use a delta deployment anyway, define USE_DELTA_DEPLOYMENT_AFTER_MERGE=true
    • +
    +
  • +
+
    +
  • ALWAYS_ENABLE_DELTA_DEPLOYMENT
      +
    • By default, delta deployment is allowed only from minor to major branches. You can force it for PR/MRs between major branches by defining variable ALWAYS_ENABLE_DELTA_DEPLOYMENT=true
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-config-home/index.html b/salesforce-ci-cd-config-home/index.html new file mode 100644 index 000000000..34b0828ae --- /dev/null +++ b/salesforce-ci-cd-config-home/index.html @@ -0,0 +1,7880 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure a Salesforce CI/CD Project using sfdx-hardis - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

CI/CD Config Home

+ + + + +

package.xml

+

A Salesforce CI/CD repository contains a file manifest/package.xml.

+
    +
  • It contains all metadatas that will be deployed by the CI server.
  • +
+ +

Overwrite Management

+ +

Delta deployments

+
    +
  • You can also use delta deployments if your project is big and you have performances issues.
  • +
+

Source retrieve issues

+

Handle cases when force:source:pull does not retrieve every updated source.

+

See how to force the retrieve of named sources

+
+

destructiveChanges.xml

+

A Salesforce CI/CD repository contains a file manifest/destructiveChanges.xml.

+
    +
  • It contains all metadatas that will be deleted by the CI server.
  • +
+ +
+

Automated sources cleaning

+

You can configure automated cleaning of sources before creating merge requests, using command hardis:work:save

+

Those cleanings can be:

+ +
+

All configuration properties

+

.sfdx-hardis.yml allows to make your project highly configuration. Have a look at its list of configuration properties !

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-config-overwrite/index.html b/salesforce-ci-cd-config-overwrite/index.html new file mode 100644 index 000000000..e37ecd538 --- /dev/null +++ b/salesforce-ci-cd-config-overwrite/index.html @@ -0,0 +1,7893 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure overwrite management on a Salesforce CI/CD Project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Overwrite Management

+ + + + +
+

package-no-overwrite.xml

+

Definition

+

For different reasons, many metadatas are maintained manually, using production Salesforce org Setup

+

To avoid to overwrite manual updates in setup, you must define at least a manifest/package-no-overwrite.xml file. (formerly named packageDeployOnce.xml)

+

The rule is simple and must be learnt by heart:

+

Every item which is existing in package.xml AND matching package-no-overwrite.xml AND existing in the target deployment org will NOT be deployed.

+

This means that an item matching package-no-overwrite.xml will be deployed the first time, but never overwritten, so has to be manually maintained in org using Setup.

+
    +
  • This file must be located at manifest/package-no-overwrite.xml (formerly packageDeployOnce.xml)
  • +
  • It has the same format than a package.xml, but must be written manually
  • +
  • It can contain named items, or wildcards *
  • +
  • Theoretically, any metadata can be added in package-no-overwrite.xml, but here are the most commonly present:
      +
    • Connected apps
    • +
    • Dashboards
    • +
    • Named Credentials
    • +
    • Profiles
    • +
    • Remote Site Settings
    • +
    • Reports
    • +
    • SAML SSO Configuration
    • +
    • Wave items (CRM Analytics)
    • +
    +
  • +
+

Example

+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Package xmlns="http://soap.sforce.com/2006/04/metadata">
+  <!-- Approval processes can contain reference to usernames -->
+  <types>
+      <members>*</members>
+      <name>ApprovalProcess</name>
+  </types>
+  <!-- Connected apps contain org unique auth info so must never be overwritten -->
+  <types>
+      <members>*</members>
+      <name>ConnectedApp</name>
+  </types>
+  <types>
+    <!-- Apps that contain hardcoded dashboard its must be managed directly in production -->
+    <members>DeclareWork</members>
+    <members>Facturation</members>
+    <members>SomeApp2</members>
+    <name>CustomApplication</name>
+  </types>
+  <types>
+    <!-- Once a dashboard is published, it is always managed directly in production -->
+    <members>*</members>
+    <name>Dashboard</name>
+  </types>
+  <types>
+    <!-- flexipages that contain Dashboard ids -->
+    <members>Accueil_administrateur</members> 
+    <members>Accueil_administratif</members>
+    <members>Accueil_Commerciaux</members>
+    <members>Accueil_Direction</members>
+    <members>Accueil_Recrutement</members>
+    <name>Flexipage</name>
+  </types> 
+  <types>
+    <!-- Name Credentials can contain auth info that are different between dev, uat, preprod and prod: let's not overwrite them ! -->
+    <members>*</members>
+    <name>NamedCredential</name>
+  </types>  
+  <types>
+    <!-- Use permission sets -->
+    <members>*</members>
+    <name>Profile</name>
+  </types>
+  <types>
+    <!-- Remote site settings can be different between dev, uat, preprod and prod: let's not overwrite them ! -->
+    <members>*</members>
+    <name>RemoteSiteSetting</name>
+  </types>  
+  <types>
+    <!-- Reports are maintained directly in production -->
+    <members>*</members>
+    <name>Report</name>
+  </types>
+    <!-- SSO Config must be performed directly in org setup -->  
+  <types>
+      <members>*</members>
+      <name>SamlSsoConfig</name>
+  </types>
+  <!-- Wave items in case you want to manage them directly in production -->
+  <types>
+    <members>*</members>
+    <name>WaveApplication</name>
+  </types>
+  <types>
+    <members>*</members>
+    <name>WaveDashboard</name>
+  </types>
+  <types>
+    <members>*</members>
+    <name>WaveDataflow</name>
+  </types>
+  <types>
+    <members>*</members>
+    <name>WaveDataset</name>
+  </types>
+  <types>
+    <members>*</members>
+    <name>WaveRecipe</name>
+  </types>
+  <types>
+    <members>*</members>
+    <name>WaveXmd</name>
+  </types>
+  <version>53.0</version>
+</Package>
+
+

packageDeployOnChange.xml

+

packageDeployOnChange.xml is slightly different from package-no-overwrite.xml: it will deploy only if the target metadata XML is different from the source metadata XML that we want to deploy

+
    +
  • This file must be located at manifest/packageDeployOnChange.xml
  • +
  • It can contain named items, or wildcards *
  • +
  • Is has much lower performances than package-no-overwrite.xml, so must be used wisely
  • +
  • Theoretically, any metadata can be added in packageDeployOnChange.xml, but here are the most commonly present:
      +
    • Sharing Rules
    • +
    • Sharing Owner Rules
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-conga/index.html b/salesforce-ci-cd-conga/index.html new file mode 100644 index 000000000..1fda16651 --- /dev/null +++ b/salesforce-ci-cd-conga/index.html @@ -0,0 +1,7698 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure overwrite management on a Salesforce CI/CD Project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

sfdx-hardis for conga

+ + + +

Conga deployments

+

It's easy to handle the deployment of Conga Composer configuration with sfdx-hardis.

+

Please see how in the following article.

+

image

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-create-new-task/index.html b/salesforce-ci-cd-create-new-task/index.html new file mode 100644 index 000000000..a1a999dae --- /dev/null +++ b/salesforce-ci-cd-create-new-task/index.html @@ -0,0 +1,8024 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create new task on a Salesforce DX project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Create new task

+ + + + +
+

Use cases

+

You use this command when you want to :

+
    +
  • Create a dedicated new branch
  • +
  • Create a scratch org linked to the branch OR assign a dedicated sandbox to the newly created branch
  • +
+
+

Sandbox or scratch org ?

+

With SFDX, usually each member of the teams has its own sandbox or scratch org to work on it.

+

The release manager of the project can tell you if you work with scratch orgs or source-tracked sandboxes, and which sandbox to use if you are in sandbox mode.

+
+

Source-tracked sandbox mode

+

Pre-requisites (sandbox)

+

You need credentials to login on the source-tracked sandbox you'll work with. It can be:

+
    +
  • An existing source-tracked sandbox
      +
    • Existing source-tracked sandboxes must be refreshed from time to time to avoid too many conflicts, discuss with your Release Manager !
    • +
    • Release managers: When you create or refresh a sandbox, you can easily activate invalid users with a few clicks
    • +
    +
  • +
  • A new source-tracked sandbox that you can create from production org
  • +
+

It is recommended to create sandbox from the org that is related to the target git branch.

+

+

Start new task on sandbox

+

Select sandbox

+
    +
  • Open VsCode SFDX Hardis extension by clicking on Hardis Group button in VsCode left bar (loading can task several seconds)
  • +
+
    +
  • Click on Start a new task
  • +
+
    +
  • Answer the questions then select Sandbox when prompted
      +
    • If the sandbox is not proposed in the list, select the option to authenticate to your desired sandbox
    • +
    +
  • +
+

Update your sandbox ?

+
    +
  • When prompted if you want to update your sandbox:
      +
    • Select yes only if you have NO pending work in your sandbox that you'll want to publish later
        +
      • If the update script fails, you can manually deploy single metadatas using Right click -> Deploy to org (see screenshot below)
      • +
      +
    • +
    • Otherwise, select no
    • +
    +
  • +
+

Example of manual deploy of a metadata that you think could have been updated in parent branch, after an Update sandbox failure

+

+

Work

+
    +
  • +

    At the end of the script execution:

    +
      +
    • If you want to reset the sandbox tracking (meaning you don't care about the previous updates in your sandbox), you can click on command
    • +
    • Click on Open org in browser and you can start working in it :)
    • +
    +
  • +
+
+ +
+

Under the hood Under the hood

+

See details in hardis:work:new command documentation

+
+
+

Scratch Org mode

+

Pre-requisites (scratch org)

+

You need the credentials to login on the Dev Hub Org (usually the production environment)

+

Start new task on scratch org

+
    +
  • Open VsCode SFDX Hardis extension by clicking on Hardis Group button in VsCode left bar
  • +
+
    +
  • Click on Start a new task
  • +
+
    +
  • Answer the questions then select Scratch Org when prompted
      +
    • If the sandbox is not proposed in the list, select the option to authenticate to your desired sandbox
    • +
    +
  • +
+
    +
  • Wait for the sandbox creation script to be completed, and you can start working in it :)
      +
    • If you see errors while creating the sandbox, request support from the project release manager
    • +
    +
  • +
+
+

Under the hood Under the hood

+

See details in hardis:work:new command documentation

+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-deploy-major-branches/index.html b/salesforce-ci-cd-deploy-major-branches/index.html new file mode 100644 index 000000000..6ede034c8 --- /dev/null +++ b/salesforce-ci-cd-deploy-major-branches/index.html @@ -0,0 +1,7753 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deploy to major branches and orgs with Salesforce CI/CD - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Deploy to major orgs

+ + + + +
+

Minor and Major branches

+

Minor branches are individual git branches that do not have a CI/CD associated org

+

Major branches are git branches that have a CI/CD associated org, and each new commit in a major branch automatically triggers a deployment to the associated org.

+

+

Examples:

+
    +
  • Minor to major: When a merge request from dev_nico to ìntegration (1) is validated and merged, a new state (commit) is detected in branch integration, so CI server automatically deploys to associated Salesforce org Integration (2)
  • +
+
    +
  • Major to Major: When a merge request from integration to uat (3) is validated and merged, a new state (commit) is detected in branch uat, so CI server automatically deploys to associated Salesforce org UAT (4)
  • +
+
    +
  • Major to Major: When a merge request from preprod to production (5) is validated and merged, a new state (commit) is detected in branch production, so CI server automatically deploys to associated Salesforce org Production (6)
  • +
+
+

Merge requests between major branches

+
    +
  • Create a New Merge request
      +
    • Set a meaningful title, like MAJOR: recette to uat or MAJOR: uat to production
    • +
    • Make sure that Delete source after merge and Squash commits are UNCHECKED
    • +
    +
  • +
  • Click on Submit merge request
  • +
+
    +
  • Controlling jobs are automatically launched, and should pass as merge requests from minor branches has been in success
      +
    • If jobs fail, it means that you need to perform manual actions in target org, like activating features or manually rename elements if metadatas API Names has been renamed (which is a bad practice but happens)
    • +
    +
  • +
+
    +
  • Once all jobs are in success, merge the merge request
      +
    • It will automatically trigger the deployment to the associated Salesforce org
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-handle-merge-request-results/index.html b/salesforce-ci-cd-handle-merge-request-results/index.html new file mode 100644 index 000000000..2136a9897 --- /dev/null +++ b/salesforce-ci-cd-handle-merge-request-results/index.html @@ -0,0 +1,7761 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Handle Merge Request Results - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Merge Request results Home

+ + + + +

Conflicts detection

+

If you are about to overwrite the work of one of your colleagues, a conflicts message will appear.

+

+ +

Deployment simulation

+

When you create a Merge Request to a major git branch, for example integration, sfdx-hardis will simulate a deployment to the related major Salesforce org, for example Integration org.

+

It will also run Apex test classes and Apex code coverage.

+

The result will be displayed in a message on the Merge Request UI

+

+

If you see errors, please check Solve deployment errors documentation

+

Quality gate

+

Any Merge Request will trigger a technical quality gate, that will check for:

+
    +
  • Apex best practices using PMD
  • +
  • LWC best practices using eslint
  • +
  • Security issues
  • +
  • Excessive copy-pastes
  • +
+

The result will be displayed in a message on the Merge Request UI

+

+

If you see errors, please check Solve MegaLinter errors documentation

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-home/index.html b/salesforce-ci-cd-home/index.html new file mode 100644 index 000000000..617f4d61d --- /dev/null +++ b/salesforce-ci-cd-home/index.html @@ -0,0 +1,7800 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Salesforce CI/CD with sfdx-hardis - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

CI/CD Home

+ + + + +
+

Introduction

+

There are many ways to do DevOps with Salesforce, each of them have their advantages and inconveniences, like showed in the following comparison table.

+

+

You can setup and use a full CI/CD pipeline for your Salesforce projects using sfdx-hardis, with advanced features:

+ +

We provide ready to use CI/CD pipeline workflows for the following Git platforms, with results of Deployment simulation jobs as comments on Pull Requests:

+ +

Pipelines can easily be adapted to other platforms like Jenkins or TeamCity

+

If you speak fluently git, sfdx & DevOps, you can be fully autonomous to setup and use Salesforce CI/CD, otherwise you can contact us at Cloudity (or your favorite Salesforce integrator) and we'll be glad to assist you :)

+

Questions/Answers

+

As everything is open-source, there is no license costs !

+

See presentation of sfdx-hardis at Dreamforce !

+
+ +

See Slides of Dreamforce 23 session

+ + +

Here is an advanced example of a Salesforce CI/CD Pipeline that you can easily define using sfdx-hardis. +You can define much simpler branch/orgs models, to manage only RUN operations.

+

+

See detailed article on SalesforceDevOps.net

+

+

See quick demo video for a Contributor

+
+ +
+

Use sfdx-hardis CI/CD

+

Please read Contributor Guide to know how to work on CI/CD projects, as an Business consultant, a Developer or a Release Manager

+
+

Release Management

+

Please read Release Manager Guide to know how to be a release manager on Salesforce CI/CD project.

+
+

Setup sfdx-hardis CI/CD

+

Please read Setup Guide to know how to initialize and maintain a Salesforce CI/CD project.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-hotfixes/index.html b/salesforce-ci-cd-hotfixes/index.html new file mode 100644 index 000000000..649fd05f9 --- /dev/null +++ b/salesforce-ci-cd-hotfixes/index.html @@ -0,0 +1,7810 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Handle deployment of hotfix in production with Salesforce CI/CD - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Handle RUN / Hotfix to Production

+ + + +

BUILD & RUN

+

Except for projects in maintenance that contain RUN only, a project is separated into 2 sections:

+
    +
  • the RUN stream: Fast cycle, to often deploy minor changes and fixes
  • +
+
    +
  • the BUILD stream: Project cycle, to build more advanced features and enhancements, that require User Acceptance Testing
  • +
+

+

THE BUILD

+

This is the layer where you prepare the next major or minor version.

+

Such new features will go through integration level, then uat level where they will be qualified and validated by business users.

+

When the User Acceptance Test will be validated in uat org, then uat can be merged into preprod, and just after minimal tests (mostly technical), preprod will soon be merged into production.

+

Is it important that major features or enhancements are not tested directly at preprod level, because while the next version is being validated in preprod, it is not possible for the RUN to deploy anything into production.

+

THE RUN

+

Daily maintenance of the production Salesforce org must be very reactive, the RUN level will allow you to often deploy patch versions.

+

As we usually can not wait for the next minor or major version to be deployed in production, projects need a way to quickly deploy hot fixes into production. That layer is called the RUN, and is exclusively about preprod and main branches.

+

To summarize, you will publish at RUN level, but also at BUILD level, so when the BUILD will be merged in the RUN, there will be no overwrite triggering regressions.

+

The hotfix process is the following:

+

Note: in this example, we merge directly in preprod, but in more advanced organizations we can define a branch/org uat_run as intermediate layer before merging to preprod

+
    +
  • +

    IMPLEMENT HOTFIX (1)

    +
      +
    • Create new task with preprod as target when prompted, named my-very-hot-hotfix for example
    • +
    +
      +
    • Work on a dev sandbox that has been cloned from production
    • +
    +
  • +
+
    +
  • +

    DEPLOYMENT IN RUN LAYER (2)

    +
      +
    • Create Pull Request from my-very-hot-hotfix to preprod & merge it after controls (do not select “delete after merge” )
    • +
    +
      +
    • Create Pull request from preprod to main
    • +
    +
      +
    • Merge preprod to main after control checks are green.
    • +
    +
  • +
+
    +
  • +

    RETROFIT IN BUILD LAYER (3)

    +
      +
    • Create a sub-branch to integration, named retrofit-from-run for example
    • +
    +
      +
    • Using Git IDE, manually merge main (or preprod) branch into retrofit-from-run
    • +
    +
      +
    • If there are git conflicts, solve them before committing
    • +
    +
      +
    • Create Pull Request from retrofit-from-run to integration
    • +
    +
      +
    • Merge the Pull Request into integration: your retrofit from the RUN to the BUILD is over :)
        +
      • You might refresh dev sandboxes if your retrofits have lots of impacts
      • +
      +
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-merge-request-gitlab/index.html b/salesforce-ci-cd-merge-request-gitlab/index.html new file mode 100644 index 000000000..6101bdfaf --- /dev/null +++ b/salesforce-ci-cd-merge-request-gitlab/index.html @@ -0,0 +1,7720 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create a merge request using Gitlab - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

On Gitlab

+ + + +

Create a merge request using Gitlab

+
    +
  • Go in your online repository in your web browser (example: https://gitlab.com/trailheadapps/dreamhouse-lwc)
  • +
+
    +
  • Go to menu Merge Requests
  • +
+
    +
  • Create a New Merge request
  • +
+

+

+
    +
  • Click on Submit merge request
  • +
+
    +
  • Controlling jobs are automatically launched, you can now ask your release manager to validate the merge request
      +
    • If you are a developer, (or even a business consultant depending on the project organization), you may have the responsibility to make sure than controlling jobs are valid (check-deploy job and code-quality job in success) and eventually fix the errors (See Handle merge requests errors)
    • +
    +
  • +
+
    +
  • If you need to add additional updates to an existing merge requests, you just this to follow again this guide from the beginning, except the part "Create a merge request". Any new commit pushed on a branch where there is already a merge request will trigger again the control jobs.
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-packaging/index.html b/salesforce-ci-cd-packaging/index.html new file mode 100644 index 000000000..9984088a1 --- /dev/null +++ b/salesforce-ci-cd-packaging/index.html @@ -0,0 +1,7965 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Generate packages and package versions - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

sfdx-hardis for packaging

+ + + +

Pre-requisites

+

sfdx-hardis menus allow to create new packages and new package versions, but to do that you need some pre-requisites.

+
    +
  • +

    In order to generate packages, you first need a Dev Hub to link them.

    + +
  • +
+
    +
  • +

    If you need to use a namespace with a package (managed or unmanaged), you also need to link you Dev Hub and a dev org where you will create the namespace.

    + +
  • +
+
    +
  • Then you need a sfdx-hardis flavored sfdx project, that you can create with sf hardis:project:create, using scratch orgs only option.
  • +
+
    +
  • Last, create your package folder (ex: my-package) at the root of the repository, following the same structure than force-app: it will contain your package content.
  • +
+

New package

+

Use sfdx-hardis menu Packaging -> Create a new package and follow instructions (select the folder that you just created, don't use force-app)

+
+

New package version

+

Git branch

+

Create a git sub-branch of your packaging branch (for example pkg/release-v0.1.0)

+
+

Increment package version

+

Before being able to generate a new package version, you need to increment the package version in sfdx-project.json.

+
{
+  "packageDirectories": [
+    {
+      "path": "package-astran",
+      "default": true,
+      "package": "Astran",
+      "versionName": "ver 0.1",                         # Change version name here to match the incremented package version
+      "versionNumber": "0.1.0.NEXT",                    # Increment version here (Respect SEMVER or you will have errors)
+      "versionDescription": "Astran for Salesforce"
+    },
+    {
+      "path": "scratch",
+      "default": false
+    }
+  ],
+  "name": "astran",
+  "namespace": "Astran",
+  "sfdcLoginUrl": "https://my-devhub-org.salesforce.com",
+  "sourceApiVersion": "57.0"
+}
+
+
+

Run create package version command

+

Run sfdx-hardis command Packaging -> Create new package version

+

+

Select the package you want to create a version, and input an installation if necessary (otherwise let it blank)

+

+

+

After some time, the new package version will be generated, and you will be able to find its ID in your sfdx-project.json

+
{
+    ...
+      "packageAliases": {
+        "Astran": "0Ho7S0123010wZWSAU",
+        "Astran@0.1.0-1": "04t7S000000gYxPQAF",
+        "Astran@0.1.0-2": "04t7S000000gYm1QAE",
+        "Astran@0.1.0-3": "04t7S000000gYp7WAG",
+}
+
+

If you have issues, it might be because you incremented the version as a patch whereas the updates with the previous version require at least a minor version.

+

For example, 1.1.4.NEXT can fail, and 1.2.0.NEXT will pass

+
+

Test the beta version

+

(optional but recommended)

+

The latest entry is the one you can use to install the beta package version (every created package version is a beta by default)

+

Example of URL to append at the end of your org domain name: /packaging/installPackage.apexp?p0=04t7S000000gYp7QAG

+

Install the beta package in a dummy sandbox to check that its content is ok for you

+
+

Pull request to packaging branch

+

Once you decide the package is ok for you, make a Pull Request to the packaging branch (or main branch, depending on your project config)

+
+

Promote the beta

+

Once you merged your PR in packaging branch (after checking the control jobs are green), you can promote the package.

+
+

WARNING: Promoting a package is a sensitive operation, because it declares it as production-ready, then you can not remove metadatas from it, and you must respect ascending compatibility to generate new package versions !

+
+

To promote a package version, run the following command

+

sf hardis:package:version:promote

+

Example: sf hardis:package:version:promote

+

Note: When later you will create a new scratch org in a new development branch, if you have issues, just increment again the versionNumber in sfdx-project.json

+
+

Create version git tag

+

Once you promoted a package, create a git tag with the version id on the commit corresponding to your merged Pull Request

+

Example: v1.1.0

+

Push the git tag to origin

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-publish-task/index.html b/salesforce-ci-cd-publish-task/index.html new file mode 100644 index 000000000..1dc0c0ae2 --- /dev/null +++ b/salesforce-ci-cd-publish-task/index.html @@ -0,0 +1,8016 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Publish a task on a Salesforce CI/CD project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Publish your work

+ + + + +
+

Commit your updates

+

The following video shows how to perform theses operations

+
+ +

Retrieve metadatas

+

If you made updates on your org that you have not pulled yet, Use command Pull from org button to pull your latest updates in local files

+

If you updated config elements that you do not see in your local files, you may discuss with your release manager to automate force retrieve metadatas

+

Alternative: Use Org Browser

+

You can also use Salesforce extension Org Browser to manually browse and retrieve specific metadatas

+

+

Alternative: Use contextual menu

+

If Org Browser does not see items that you want to retrieve, like list views, you can right click on any listViews folder and use command SFDX: Retrieve source from org

+

+

Alternative: Use menu "Select and retrieve"

+

If it is not possible to use pull configuration, you may retrieve metadatas using Select and retrieve button (but it will retrieve locally many files and it will be harder to select the ones you really need, select carefully the items that you stage and commit)

+

Stage and commit

+

In VsCode Git extension, stage and commit created, updated and deleted files that you want to publish

+
    +
  • By selecting the metadata files you can see the differences with the previous versions, to know if you want to publish or not an updated file
  • +
+
    +
  • Never use Stage all function
  • +
+
    +
  • If you see standard items like standard fields that do not contain customizations, do not commit them
  • +
+
    +
  • Important: If you think that your sandbox may not be up to date according to elements published by your colleagues, look closely at the diff on those items, and stage only the updates that you want to publish
  • +
+

+

+

+
+

Prepare merge request

+
    +
  • Once your commit is completed, run command Save / publish my current task button to prepare your merge request.
  • +
+
    +
  • As you committed your files like explained in the previous section, select option Message my commit is ready when prompted.
  • +
+
    +
  • Wait for the script to complete, and select Push commit to server when prompted
  • +
+
+

Under the hood Under the hood

+

The script performs the following operations:

+
    +
  • Update manifest/package.xml automatically according to the committed updates
  • +
  • Clean XML of metadatas according to .sfdx-hardis.yml config property autoCleanTypes and autoRemoveUserPermissions
  • +
  • New git commit with automated updates
  • +
  • Git push commit to git server
  • +
+

More details in hardis:work:save command documentation

+
+
+

Create merge request

+

It is now time to create your merge request to technically publish your updates at the upper level !

+

Depending on the CI platform you use, follow the related guide.

+
+

If you are publishing to a RUN branch (ex: preprod), AND the project also has a BUILD branch (ex: integration), you need to notify the release manager +He/she will have to retrofit your updates once published

+

If you are working with a ticketing system like JIRA, make sure to add the full url of the tickets in the MR/PR description, so it will help for the release management. +For example, use https://sfdx-hardis.atlassian.net/browse/CLOUDITY-4 , not CLOUDITY-4

+
+

Using Gitlab

+

See Create a merge request using Gitlab

+

Using Azure

+

See Create a merge request using Azure

+

Using GitHub

+

See Create a merge request using Github

+

Check merge request results

+

After you create your merge request, check its control jobs results !

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-pull-request-azure/index.html b/salesforce-ci-cd-pull-request-azure/index.html new file mode 100644 index 000000000..3ff508e3d --- /dev/null +++ b/salesforce-ci-cd-pull-request-azure/index.html @@ -0,0 +1,7720 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create a pull request using Azure - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

On Azure

+ + + +

Create a Pull Request using Azure

+
    +
  • Go in your online repository in your web browser (example: https://dev.azure.com/mycompany/trailheadapps/dreamhouse-lwc)
  • +
+
    +
  • Go to menu Repos -> Pull Requests
  • +
+
    +
  • Click on New pull request
  • +
+

+

+
    +
  • Click on Create
  • +
+
    +
  • Controlling jobs are automatically launched, you can now ask your release manager to validate the merge request
      +
    • If you are a developer, (or even a business consultant depending on the project organization), you may have the responsibility to make sure than controlling jobs are valid (check-deploy job and code-quality job in success) and eventually fix the errors (See Handle merge requests errors)
    • +
    +
  • +
+
    +
  • If you need to add additional updates to an existing merge requests, you just this to follow again this guide from the beginning, except the part "Create a merge request". Any new commit pushed on a branch where there is already a merge request will trigger again the control jobs.
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-pull-request-github/index.html b/salesforce-ci-cd-pull-request-github/index.html new file mode 100644 index 000000000..c3da15f1c --- /dev/null +++ b/salesforce-ci-cd-pull-request-github/index.html @@ -0,0 +1,7699 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create a pull request using GitHub - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

On Github

+ + + +

Create a Pull Request using GitHub

+

Not documented yet, see Create a pull request using Azure, it's almost the same !

+

You can also create a pull request here to update this documentation :)

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-release-home/index.html b/salesforce-ci-cd-release-home/index.html new file mode 100644 index 000000000..bce173dbc --- /dev/null +++ b/salesforce-ci-cd-release-home/index.html @@ -0,0 +1,7649 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Salesforce CI/CD Release Manager Guide - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Release Manager Home

+ + + +

In order to respect the best DevOps practices, it's highly recommended for project teams to have members taking the role of Release Manager

+

The release manager(s) responsibilities are:

+ +

You can also see specific use cases documentation

+ + + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-retrieve/index.html b/salesforce-ci-cd-retrieve/index.html new file mode 100644 index 000000000..0007966f4 --- /dev/null +++ b/salesforce-ci-cd-retrieve/index.html @@ -0,0 +1,7728 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fix sfdx pull issues - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Source retrieve issues

+ + + +

Automated force retrieve

+

It happens that when calling sf hardis:scratch:pull, some elements are not retrieved.

+

The most usual cases are updates on:

+
    +
  • CustomApplication
  • +
  • RecordTypes
  • +
+

See how to configure .sfdx-hardis to force the retrieve of metadatas with autoRetrieveWhenPull property.

+

Manual Retrieve

+

You can also use command to manually retrieve metadatas, but it will pull a lot of metadatas so you will have to carefully select them for your commit.

+
+

Under the hood Under the hood

+

See details in hardis:source:retrieve command documentation

+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-activate-org/index.html b/salesforce-ci-cd-setup-activate-org/index.html new file mode 100644 index 000000000..c904c1c32 --- /dev/null +++ b/salesforce-ci-cd-setup-activate-org/index.html @@ -0,0 +1,7740 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Activate Dev Hub and Sandbox Tracking - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

DevHub and Sandbox Tracking

+ + + +

Dev Hub and sandbox tracking

+

You must declare an org (usually production) as a DevHub and activate sandbox tracking to be able to work with advanced features of Salesforce DX

+
    +
  • Login to Dev Hub org
  • +
+
    +
  • Go to Setup -> Dev Hub
  • +
+ +
    +
  • Activate Sandbox tracking
      +
    • If sandbox were already existing, you need to refresh them if you want their source tracking to be activated
    • +
    • To use Create from from an existing sandbox, you need to refresh it before the cloning, else the nex sandbox won't have the tracking activated
    • +
    +
  • +
+

Major orgs

+

When there is a new state of a major branch (after a merge), a deployment to the related major Org will be automatically triggered by the CI server.

+

You need to have a Salesforce sandbox corresponding to each major branch.

+

Example:

+
    +
  • Branch preprod - create a sandbox named Preprod, cloned from Production org
  • +
  • Branch uat - create a sandbox named UAT, cloned from PreProd org
  • +
  • Branch integration - create a sandbox named Integration, cloned from UAT org
  • +
+

If you are converting an existing project to CI/CD and already have existing orgs, just create an org Integration, and you'll refresh later UAT and PreProd, once your setup will be more advanced.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-auth-azure/index.html b/salesforce-ci-cd-setup-auth-azure/index.html new file mode 100644 index 000000000..4416438c7 --- /dev/null +++ b/salesforce-ci-cd-setup-auth-azure/index.html @@ -0,0 +1,7613 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Configure Azure CI/CD variables - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Configure Azure CI/CD variables

+ + + +

Define sfdx-hardis environment variables

+
    +
  • Go to Project -> Pipelines
  • +
  • Select your pipeline
  • +
  • Click on Edit , then on Variables
  • +
  • Input variable name and value
  • +
  • Don't forget to click on save !
  • +
+

+

More info: Azure documentation

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-auth-bitbucket/index.html b/salesforce-ci-cd-setup-auth-bitbucket/index.html new file mode 100644 index 000000000..f013e40e2 --- /dev/null +++ b/salesforce-ci-cd-setup-auth-bitbucket/index.html @@ -0,0 +1,7609 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Configure Bitbucket CI/CD variables - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Configure Bitbucket CI/CD variables

+ + + +

Define sfdx-hardis environment variables

+
    +
  • Go to Project -> Repository Settings > Repository Variables (you must have Bitbucket authorizations to access this menu)
  • +
+

+

More info: BitBucket documentation

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-auth-github/index.html b/salesforce-ci-cd-setup-auth-github/index.html new file mode 100644 index 000000000..9bf2d5819 --- /dev/null +++ b/salesforce-ci-cd-setup-auth-github/index.html @@ -0,0 +1,7617 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Configure GitHub CI/CD variables - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Configure GitHub CI/CD variables

+ + + +

Define sfdx-hardis environment variables

+
    +
  • Go to Repository -> Settings > Secret and variables -> Actions (you must have Github authorizations to access this menu)
  • +
+

+
    +
  • Create the new secret with the following info:
      +
    • name: YOUR_VARIABLE_NAME
    • +
    • value: Your variable value
    • +
    +
  • +
+

+

More info: GitHub documentation

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-auth-gitlab/index.html b/salesforce-ci-cd-setup-auth-gitlab/index.html new file mode 100644 index 000000000..b9f69ee6d --- /dev/null +++ b/salesforce-ci-cd-setup-auth-gitlab/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Configure Gitlab CI/CD variables - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Configure Gitlab CI/CD variables

+ + + +

Define sfdx-hardis environment variables

+
    +
  • Go to Project -> Settings > CI/CD -> Variables (you must have Gitlab authorizations to access this menu)
  • +
+

+
    +
  • Create the variable with the following info:
      +
    • name: YOUR_VARIABLE_NAME
    • +
    • value: Your variable value
    • +
    • Select Mask variable if the value is secured, like credentials or tokens
    • +
    • Unselect Protected variable
    • +
    +
  • +
+

+

More info: Gitlab documentation

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-auth-jenkins/index.html b/salesforce-ci-cd-setup-auth-jenkins/index.html new file mode 100644 index 000000000..79ee1d296 --- /dev/null +++ b/salesforce-ci-cd-setup-auth-jenkins/index.html @@ -0,0 +1,7613 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Configure Jenkins CI/CD credentials - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Configure Jenkins CI/CD credentials

+ + + +

Define sfdx-hardis environment variables

+
    +
  • Go to Dashboard -> Manage Jenkins
  • +
  • Under Security tab click on Credentials -> global credentials
  • +
  • Click on Add credential , then choose Secret text
  • +
  • Input variable name and value
  • +
  • Don't forget to click on create !
  • +
+

+

More info: Jenkins documentation

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-auth/index.html b/salesforce-ci-cd-setup-auth/index.html new file mode 100644 index 000000000..119adec3a --- /dev/null +++ b/salesforce-ci-cd-setup-auth/index.html @@ -0,0 +1,7752 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure CI Server authentication to Salesforce orgs - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

CI Server Authentication

+ + + +

Major orgs

+

To automate deployments from major branches to their related org, you need to configure the secure authentication from CI server to a SF connected app.

+

Note: You need openssl installed on your computer (available in Git bash)

+
    +
  • Remain in your initialization branch cicd, or a sub branch of your lowest level major branch (usually integration)
  • +
  • For each major branch to link to an org, run the sfdx-hardis command Configuration -> Configure Org CI Authentication (sf hardis:project:configure:auth)
  • +
+

For example, run the command for integration, uat, preprod and production major branches.

+
+

If messages ask you to run twice the same command, it's normal, it's for technical reasons :)

+

If you have errors in your apex tests classes, you may not be able to configure the app for Production org. +You will need do create the connected app manually by following the instructions in yellow in the error message. +You can do it later, after having succeeded to merge the first merge request in lower major branch (usually integration)

+
+
+ +
+

Under the hood Under the hood

+

This command will create/update:

+
    +
  • .sfdx-hardis.yml configuration file (repo)
  • +
  • Self signed certificate (encrypted in repo as .key)
  • +
  • Connected App (uploaded to org via metadata api)
  • +
  • CI environment variables (manually set in CI/CD server UIs)
  • +
+

At runtime, we use OAuth 2.0 JSON Web Tokens (JWT) bearer flow with the client Id stored in secured CI/CD Variable + the Certificate decrypted on the fly using token stored in secured CI/CD variable.

+
+

See how to set CI variables on different Git providers:

+ +

Dev Hub

+

If you are using scratch orgs, you need to also configure authentication for the Dev Hub (even if you already configured authentication for production org)

+

To do that, run the following command

+
sf hardis:project:configure:auth --devhub
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-existing-org/index.html b/salesforce-ci-cd-setup-existing-org/index.html new file mode 100644 index 000000000..75829b05f --- /dev/null +++ b/salesforce-ci-cd-setup-existing-org/index.html @@ -0,0 +1,7965 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Initialize sfdx sources from Salesforce org - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Init from Existing Org

+ + + +

If this is a new Salesforce project, or if you want to setup CI/CD in incremental mode, you can skip this step and directly go to Create first merge request.

+

Thanks to tracked sandboxes, you can also decide to opt for an half-incremental init, with only some metadata types like Apex, LWC & Permission sets. In that case retrieve manually the metadatas you need, for example with Org Browser.

+

If you want to go for a full init setup, follow the steps below !

+ +

Retrieve Metadatas

+
    +
  • Run the following command that will retrieve locally all the metadatas of production org
  • +
+

sf hardis:org:retrieve:sources:dx --shape -u YOURSOURCEORGUSERNAME

+ +

Example :

+
    +
  • sf hardis:org:generate:packagexmlfull --targetusername nico@example.com --outputfile ./packagexmlfull.xml
  • +
  • Remove Document part on packagexmlfull.xml +
        <types>
    +        <members>Doc1</members>
    +        <members>Doc2</members>
    +        <members>Doc3</members>
    +        <name>Document</name>
    +    </types>
    +
  • +
  • sf project:retrieve:start -x ./packagexmlfull.xml --ignore-conflicts
  • +
+

Automated Metadatas Cleaning

+

You have way too many metadatas locally, including standard and managed items that are not customize so are not needed in the repository.

+

Proceed to the following steps to automatically remove many of them, then proceed to the final manual cleaning

+

Remove Managed items

+

Run the following command to delete all elements with a namespace.

+
sf hardis:project:clean:manageditems --namespace SOMENAMESPACE
+
+

Remove (hidden) files

+

Some items have no namespace but are managed anyway, and contain (hidden), so they must me deleted with the following command.

+
sf hardis:project:clean:hiddenitems
+
+

Remove empty items

+

Some files are empty and do not need to be kept in repository, remove them using the following command.

+
sf hardis:project:clean:emptyitems
+
+

Standard objects without custom

+

The retrieve command pulled all standard objects and fields.

+

Those which has never been customized do not need to remain in repository, delete them using the following command (that can take some time)

+
sf hardis:project:clean:standarditems
+
+

Manual Metadata Cleaning

+

Automated Metadata cleaning removed a lot of items, but many are remaining that are useless in the repo.

+

Manually delete files (or even folders) that are maintained directly in production org

+
    +
  • applications: Delete the ones starting with standard__
  • +
  • àppMenus: Delete all folder
  • +
  • cleanDataServices: Delete all folder
  • +
  • dashboards: Delete all user dashboards
  • +
  • emailServices: Delete all folder
  • +
  • flowDefinitions : Delete all folder (Salesforce now uses flow folder)
  • +
  • installedPackages: Delete all folder
  • +
  • layouts: Delete all standard layouts that has not been customized
  • +
  • profiles : Delete all standard profiles
  • +
  • profilePasswordPolicies: Delete all folder
  • +
  • profileSessionSettings: Delete all folder,
  • +
  • reports: Delete all reports that have been created directly in production org
  • +
+

Retrieve installed packages

+

Run the following command to retrieve packages installed on production org

+

sf hardis:org:retrieve:packageconfig -u YOUR_PROD_ORG_USER

+

This will update file config/.sfdx-hardis.yml

+
    +
  • Keep only the packages that you are using in all orgs.
  • +
  • Define installDuringDeployments property to true if you need this package installed on all orgs
  • +
  • Define installOnScratchOrgs property to true if you are using scratch orgs and need this package installed when you create a new scratch org
  • +
+

Example:

+
installedPackages:
+  - Id: 0A37Z000000AtDYSA0
+    SubscriberPackageId: 033i0000000LVMYAA4
+    SubscriberPackageName: Marketing Cloud
+    SubscriberPackageNamespace: et4ae5
+    SubscriberPackageVersionId: 04t6S000001UjutQAC
+    SubscriberPackageVersionName: Marketing Cloud
+    SubscriberPackageVersionNumber: 238.3.0.2
+    installOnScratchOrgs: true
+    installDuringDeployments: true
+  - Id: 0A35r0000009F9CCAU
+    SubscriberPackageId: 033b0000000Pf2AAAS
+    SubscriberPackageName: Declarative Lookup Rollup Summaries Tool
+    SubscriberPackageNamespace: dlrs
+    SubscriberPackageVersionId: 04t5p000001BmLvAAK
+    SubscriberPackageVersionName: Release
+    SubscriberPackageVersionNumber: 2.15.0.9
+    installOnScratchOrgs: true
+    installDuringDeployments: true
+
+

Create first merge request

+
+

Don't forget to run and to follow other instructions before creating your initial merge request !

+
+

Time to create the first merge request !

+

You'll probably have many updates to perform in new commits before having all jobs in green :)

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-git/index.html b/salesforce-ci-cd-setup-git/index.html new file mode 100644 index 000000000..c76656d67 --- /dev/null +++ b/salesforce-ci-cd-setup-git/index.html @@ -0,0 +1,7885 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Git Branches for Salesforce CI/CD - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ + + + + + + +

Init Git repository

+ + + + +

Create git repository

+

Your git repository will be used to store and manage the versioning of your Salesforce DX sources

+
    +
  • Create a new repository, for example myclient-sfdx
      +
    • Select Initialize repository with a README
    • +
    +
  • +
+

Create major branches

+

In Repository -> Branches, create the branch tree according to the complexity of your project

+

Below are examples of branches tree that you can define.

+

Small project

+
    +
  • main (will be related to Production org)
      +
    • preprod (will be related to PreProd org)
    • +
    +
  • +
+

Medium project

+
    +
  • main (will be related to Production org)
      +
    • preprod (will be related to PreProd org)
        +
      • integration (will be related to Integration org)
      • +
      +
    • +
    +
  • +
+

Complex project

+
    +
  • main (will be related to Production org)
      +
    • preprod (will be related to PreProd org)
        +
      • uat (will be related to UAT org)
          +
        • integration (will be related to Integration org)
        • +
        +
      • +
      +
    • +
    +
  • +
+

Example of branching strategy

+

+

Protect major branches

+

To avoid messes, protected branches must be updated only using Merge Requests

+
    +
  • Go to menu Settings -> Repository
  • +
  • Define your developments target branch (usually integration) as Default Branch
  • +
  • Protect all branches that will have a corresponding Salesforce org (main, preprod, uat, integration...)
  • +
+

Recommended practice is to set Maintainer in Allowed to merge to all protected branches, except integration

+

Example

+

protected branches

+

Define merge rules

+

Let's make sure that merge request jobs will be valid before being merged ! (can be deactivated later but at your own risk)

+
    +
  • Go in menu Settings -> General , then in section Merge requests (expand)
  • +
  • Leave all default values, except checkbox Pipelines must succeed that must be checked
  • +
+

merge checks

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-home/index.html b/salesforce-ci-cd-setup-home/index.html new file mode 100644 index 000000000..17d07a9e9 --- /dev/null +++ b/salesforce-ci-cd-setup-home/index.html @@ -0,0 +1,7742 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Setup a Salesforce CI/CD Project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

CI/CD Setup Home

+ + + + +
+

Pre-requisites

+ +

Setup steps

+ + + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-init-project/index.html b/salesforce-ci-cd-setup-init-project/index.html new file mode 100644 index 000000000..300f02f3f --- /dev/null +++ b/salesforce-ci-cd-setup-init-project/index.html @@ -0,0 +1,7682 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Initialize SFDX Project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Init SFDX Project

+ + + + +
    +
  • Create a new git branch named cicd under your lower major branch (usually integration)
  • +
+
    +
  • Run command Configuration -> Create new sfdx project (sf hardis:project:create) and select options to create a new sfdx-hardis project.
  • +
+
    +
  • Open file manifest/package.xml and replace the content by the following code
  • +
+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Package xmlns="http://soap.sforce.com/2006/04/metadata">
+    <version>59.0</version> <!-- use current latest Salesforce api version -->
+</Package>
+
+
    +
  • IF you are using Gitlab CI and sandboxes only (not scratch orgs), open gitlab-ci-config.yml at the root of the repository, and set variable USE_SCRATCH_ORGS to "false"
  • +
+
    +
  • Depending your git provider, keep the related workflow files and delete the others
      +
    • Gitlab
        +
      • gitlab-ci.yml
      • +
      • gitlab-ci-config.yml
      • +
      +
    • +
    • Azure
        +
      • azure-pipelines-checks.yml
      • +
      • azure-pipelines-deployment.yml
      • +
      +
    • +
    • GitHub:
        +
      • Folder .github/workflows
      • +
      +
    • +
    • Bitbucket
        +
      • bitbucket-pipelines.yml
      • +
      +
    • +
    +
  • +
+
+

Some workflow files contain additional configuration instructions, please read the comments at the beginning of the files !

+
+

You can now go to step Setup CI Authentication

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-api/index.html b/salesforce-ci-cd-setup-integration-api/index.html new file mode 100644 index 000000000..43da8062c --- /dev/null +++ b/salesforce-ci-cd-setup-integration-api/index.html @@ -0,0 +1,8294 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure API notifications from Salesforce CI/CD - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Grafana

+ + + +

API Integration

+

You can send notifications to an external API endpoints, for example to build Grafana dashboards

+
    +
  • Deployment from a major branch to a major Salesforce org (ex: integration git branch to Integration Org)
  • +
  • Salesforce Org Monitoring
      +
    • Latest updates
    • +
    • Failing apex tests
    • +
    • Monitoring checks notifications
    • +
    +
  • +
+

Logs Configuration

+

Define the following CI/CD variables:

+
    +
  • NOTIF_API_URL : API endpoint
  • +
  • NOTIF_API_BASIC_AUTH_USERNAME : Basic auth username (if using Basic Auth)
  • +
  • NOTIF_API_BASIC_AUTH_PASSWORD : Basic auth password/token (if using Basic Auth)
  • +
  • NOTIF_API_BEARER_TOKEN : Bearer token (if using bearer auth)
  • +
+

Examples of configuration:

+
NOTIF_API_URL=https://logs-prod-012.grafana.net/loki/api/v1/push
+NOTIF_API_BASIC_AUTH_USERNAME=3435645645
+NOTIF_API_BASIC_AUTH_PASSWORD=GHTRGDHDHdhghg23345DFG^sfg!ss
+
+
NOTIF_API_URL=https://my.custom.endpoint.net
+NOTIF_API_BEARER_TOKEN=DDHGHfgfgjfhQESRDTHFKGKHFswgFHDHGDH
+
+

Example of logs sent to Loki:

+
{
+  "streams": [
+    {
+      "stream": {
+        "source": "sfdx-hardis",
+        "type": "LINT_ACCESS",
+        "orgIdentifier": "hardis-group",
+        "gitIdentifier": "monitoring-hardis-org/monitoring_hardis_group",
+        "severity": "warning"
+      },
+      "values": [
+        [
+          "1715530820301000000",
+          "{\"metric\":3,\"_dateTime\":\"2024-05-12T16:20:20.301Z\",\"_severityIcon\":\"⚠️\",\"_title\":\"⚠️ 3 custom elements have no access defined in any Profile or Permission set in monitoringhardisgroup\",\"_logBodyText\":\"⚠️ 3 custom elements have no access defined in any Profile or Permission set in monitoringhardisgroup\\n\\nfield\\n\\n• Activity.DBActivityType__c\\n\\n• Activity.IdExterneCARRENET__c\\n\\n• Activity.Typederendezvous_c\\n\\nLinks:\\n\\n  View Job: https://gitlab.onpremise.com/busalesforce/hardis-group-interne/monitoring-hardis-org/-/jobs/12345\\n\\nPowered by sfdx-hardis: https://sfdx-hardis.cloudity.com\",\"_logElements\":[{\"type\":\"field\",\"element\":\"Activity.DB_Activity_Type__c\",\"severity\":\"warning\",\"severityIcon\":\"⚠️\"},{\"type\":\"field\",\"element\":\"Activity.IdExterneCARRENET__c\",\"severity\":\"warning\",\"severityIcon\":\"⚠️\"},{\"type\":\"field\",\"element\":\"Activity.Type_de_rendez_vous__c\",\"severity\":\"warning\",\"severityIcon\":\"⚠️\"}],\"_metrics\":{\"ElementsWithNoProfileOrPermissionSetAccess\":3},\"_metricsKeys\":[\"ElementsWithNoProfileOrPermissionSetAccess\"],\"_jobUrl\":\"https://gitlab.onpremise.com/busalesforce/hardis-group-interne/monitoring-hardis-org/-/jobs/399629\"}"
+        ]
+      ]
+    }
+  ]
+}
+
+

Metrics Configuration

+

Additionally, you can send metrics in Prometheus format to a secondary API endpoint.

+

The configuration is the same than for logs, but with different variable names.

+
    +
  • NOTIF_API_METRICS_URL
  • +
  • NOTIF_API_METRICS_BASIC_AUTH_USERNAME
  • +
  • NOTIF_API_METRICS_BASIC_AUTH_PASSWORD
  • +
  • NOTIF_API_METRICS_BEARER_TOKEN
  • +
+

Example of configuration:

+
NOTIF_API_METRICS_URL=https://influx-prod-72-prod-eu-west-2.grafana.net/api/v1/push/influx/write
+NOTIF_API_METRICS_BASIC_AUTH_USERNAME=345673
+NOTIF_API_METRICS_BASIC_AUTH_PASSWORD=GHTRGDHDHdhghg23345DFG^sfg!ss
+
+

Example of metrics sent to Prometheus

+
ApexTestsFailingClasses,source=sfdx-hardis,type=APEX_TESTS,orgIdentifier=hardis-group,gitIdentifier=monitoring-hardis-org/monitoring_hardis_group metric=0.00
+ApexTestsCodeCoverage,source=sfdx-hardis,type=APEX_TESTS,orgIdentifier=hardis-group,gitIdentifier=monitoring-hardis-org/monitoring_hardis_group metric=90.00
+
+

Troubleshooting

+

If you want to see the content of the API notifications in execution logs, you can define NOTIF_API_DEBUG=true

+

Grafana Setup

+

If you don't have a Grafana server, you can use Grafana Cloud Free Tier (14 days of logs & metrics retention + 3 users, no credit card required, free forever)

+

Create Grafana Account

+

Create a Grafana Cloud Free account at this url

+

+
+

Input a Grafana Cloud org name (sfdxhardis in the example)

+

+
+

Next screen, you can skip setup

+

+

Gather URLs & auth info

+

Create a notepad when you copy paste the following text

+
NOTIF_API_URL=
+NOTIF_API_BASIC_AUTH_USERNAME=
+NOTIF_API_BASIC_AUTH_PASSWORD=
+NOTIF_API_METRICS_URL=
+NOTIF_API_METRICS_BASIC_AUTH_USERNAME=
+NOTIF_API_METRICS_BASIC_AUTH_PASSWORD=
+
+

Get Loki configuration

+

Go to Connections -> Data Sources and click on grafanacloud-YOURORGNAME-logs (Loki)

+

+
+

Build Logs push url

+
    +
  • Copy value of Connection URL (something like https://logs-prod-012.grafana.net/)
  • +
  • Add /loki/api/v1/push at the end
  • +
  • Copy value to variables NOTIF_API_URL
  • +
+

Example: NOTIF_API_URL=https://logs-prod-012.grafana.net/loki/api/v1/push

+

Copy value of Authentication -> User and paste it with variable NOTIF_API_BASIC_AUTH_USERNAME

+

Example: NOTIF_API_BASIC_AUTH_USERNAME=898189

+

Leave NOTIF_API_BASIC_AUTH_PASSWORD empty for now, you can't get it here

+

+

See Grafana documentation for more info

+

Get Prometheus configuration

+

Go to Connections -> Data Sources and click on grafanacloud-YOURORGNAME-prom (Prometheus)

+

+
+

Build Metrics push url

+
    +
  • Copy value of Connection URL (something like https://prometheus-prod-24-prod-eu-west-2.grafana.net/api/prom)
  • +
  • Replace prometheus by influx
  • +
  • Replace api/prom by api/v1/push/influx/write
  • +
  • Then copy value to variables NOTIF_API_METRICS_URL
  • +
+

Example: NOTIF_API_METRICS_URL=https://influx-prod-24-prod-eu-west-2.grafana.net/api/v1/push/influx/write

+

Copy value of Authentication -> User and paste it with variable NOTIF_API_METRICS_BASIC_AUTH_USERNAME

+

Example: NOTIF_API_METRICS_BASIC_AUTH_USERNAME=1596503

+

Leave NOTIF_API_METRICS_BASIC_AUTH_PASSWORD empty for now, you can't get it here

+

+

See Grafana documentation for more info

+

Create Service Account

+

Go to Administration -> Users and Access -> Cloud Access Policies, then click on Create Access Policy

+

+
+

Create the access policy

+
    +
  • Define sfdxhardis as name and display name
  • +
  • Select write for items metrics, logs, traces, profiles, alerts (only metrics and logs are used today, but who knows hat new features we'll release in the future !)
  • +
  • Click on Create
  • +
+

+
+

On the new Access Policy sfdxhardis, click on Add Token at the bottom right

+

+
+

Name it sfdxhardis-token, let No expiration then click Create

+

+
+

On the next screen, click on Copy to clipboard then paste in your notepad in front of variables NOTIF_API_BASIC_AUTH_PASSWORD and NOTIF_API_METRICS_BASIC_AUTH_PASSWORD

+

+

Example:

+
NOTIF_API_BASIC_AUTH_PASSWORD=glc_eyJvIjoiMTEzMjI4OCIsIm4iOiJzZmR4aGFyZGlzLXNmZHhoYXJkaXMtdG9rZW4iLCJrIjoiN0x6MzNXS0hKR1J5ODNsMVE5NU1IM041IiwibSI6eyJyXN0LTIifX0=
+NOTIF_API_METRICS_BASIC_AUTH_PASSWORD=glc_eyJvIjoiMTEzMjI4OCIsIm4iOiJzZmR4aGFyZGlzLXNmZHhoYXJkaXMtdG9rZW4iLCJrIjoiN0x6MzNXS0hKR1J5ODNsMVE5NU1IM041IiwibSI6eyJyXN0LTIifX0=
+
+

Configure CI variables on repository

+

Now configure the 6 variables on the monitoring repository. (Ignore other paragraphs, except those who explain how to modify the pipeline YML to access protected variables)

+ +

Now you can force a run of your monitoring job (just add a dumb commit on a monitoring_xxxx branch to trigger it)

+

Optionally , you can look in the logs, you should see [ApiProvider] and [ApiMetricProvider] items.

+

+

Download sfdx-hardis dashboards

+

Download all sfdx-hardis Dashboard JSON files from this sfdx-hardis repo folder

+

+

Create Dashboard folder

+

Go in menu Dashboards then click on New then New folder

+

+
+

Create folder Sfdx-hardis Dashboards

+

+

Import default sfdx-hardis Grafana Dashboards

+

For each downloaded Dashboard JSON file, process the following actions.

+

Click New then Import

+

+
+

Click on Upload Dashboard JSON File and select one of the Dashboards JSON files you downloaded on your computer.

+

+
+
    +
  • Let Name, Folder and UID default values
  • +
  • Select your Loki or Prometheus source. They can be:
      +
    • grafanacloud-YOURORGNAME-logs (Loki)
    • +
    • grafanacloud-YOURORGNAME-prom (Prometheus)
    • +
    +
  • +
+

+
+

Click Import

+

+

__

+

Repeat the operation for all Dashboard JSON files, and you're all set !

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-azure-boards/index.html b/salesforce-ci-cd-setup-integration-azure-boards/index.html new file mode 100644 index 000000000..825a3a66a --- /dev/null +++ b/salesforce-ci-cd-setup-integration-azure-boards/index.html @@ -0,0 +1,7834 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Integrations between sfdx-hardis and Azure Boards Work Items - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Azure Boards

+ + + + +

Azure Boards integration

+

If you use Azure Work Items on your project, sfdx-hardis can use it to enrich its integrations

+

Sfdx-hardis will automatically analyze commits and PR/MR descriptions to collect Work Items references !

+

Make sure to link your Work Items to your Pull Requests before submitting them !

+

Update Work Items

+

Add comments and tags on JIRA tickets when they are deployed in a major org

+

Default tag is UPPERCASE(branch_name) + "_DEPLOYED".

+

To override it, define env variable DEPLOYED_TAG_TEMPLATE, that must contain {BRANCH}.

+

Example: DEPLOYED_TO_{BRANCH}

+

+

Technical notes

+

This integration use the following variables, that must be available from the pipelines:

+
    +
  • SYSTEM_COLLECTIONURI
  • +
  • SYSTEM_ACCESSTOKEN
  • +
  • SYSTEM_TEAMPROJECT
  • +
  • BUILD_REPOSITORY_ID
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-azure/index.html b/salesforce-ci-cd-setup-integration-azure/index.html new file mode 100644 index 000000000..d1df45ecf --- /dev/null +++ b/salesforce-ci-cd-setup-integration-azure/index.html @@ -0,0 +1,7783 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Integrations between sfdx-hardis and Azure Pipelines - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Azure DevOps

+ + + +

Azure Pull Request notes

+

In order to avoid to have to open job logs to see deployment errors, sfdx-hardis can post them as a thread on the Pull Request UI

+

To use this capability:

+ +
    +
  • You must allow Contribute and Contribute to Pull Requests on your Build Service (Settings -> Repositories -> Select your build service)
  • +
+

Screenshot

+

Everytime you will make a pull request, the CI job will post its result as comment !

+
    +
  • Example with deployment errors
  • +
+

+
    +
  • Example with failing test classes
  • +
+

+
    +
  • Example when all is ok :)
  • +
+

+

Notes:

+
    +
  • This integration works with sfdx-hardis pipeline, but also on home-made pipelines, just call sf hardis:project:deploy:start instead of sf project:deploy:start !
  • +
+
    +
  • This integration use the following variables:
      +
    • SYSTEM_ACCESSTOKEN: $(System.AccessToken)
    • +
    • CI_SFDX_HARDIS_AZURE_TOKEN: $(System.AccessToken)
    • +
    • SYSTEM_COLLECTIONURI: $(System.CollectionUri)
    • +
    • SYSTEM_JOB_DISPLAY_NAME: $(System.JobDisplayName)
    • +
    • SYSTEM_JOB_ID: $(System.JobId)
    • +
    • SYSTEM_PULLREQUEST_PULLREQUESTID: $(System.PullRequest.PullRequestId)
    • +
    • SYSTEM_TEAMPROJECT: $(System.TeamProject)
    • +
    • BUILD_BUILD_ID: $(Build.BuildId)
    • +
    • BUILD_REPOSITORY_ID: $(Build.Repository.ID)
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-bitbucket/index.html b/salesforce-ci-cd-setup-integration-bitbucket/index.html new file mode 100644 index 000000000..01c30534c --- /dev/null +++ b/salesforce-ci-cd-setup-integration-bitbucket/index.html @@ -0,0 +1,7770 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Integrations between sfdx-hardis and Bitbucket Pipelines - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

BitBucket

+ + + +

Bitbucket Pull Request comments

+

In order to avoid to have to open job logs to see deployment errors, sfdx-hardis can post them as a comment on the Pull Request UI

+

To use this capability:

+
    +
  • Go to Repository Settings -> Access Tokens Create Repository Access Token with the following scopes:
      +
    • pullrequest
    • +
    • pullrequest:write
    • +
    • repository
    • +
    • repository:write
    • +
    +
  • +
  • Go to Repository Settings > Repository Variables Create a variable named CI_SFDX_HARDIS_BITBUCKET_TOKEN and provide the access token value
  • +
+

Everytime you will make a pull request, the CI job will post its result as a comment !

+
    +
  • Example when all is ok :) +
  • +
+

Notes:

+
    +
  • This integration works with sfdx-hardis pipeline, but also on home-made pipelines, just call sf hardis:project:deploy:start instead of sf project:deploy:start !
  • +
+
    +
  • This integration uses the following variables:
      +
    • CI_SFDX_HARDIS_BITBUCKET_TOKEN
    • +
    • BITBUCKET_WORKSPACE
    • +
    • BITBUCKET_REPO_SLUG
    • +
    • BITBUCKET_BRANCH
    • +
    • BITBUCKET_PR_ID
    • +
    • BITBUCKET_BUILD_NUMBER
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-email/index.html b/salesforce-ci-cd-setup-integration-email/index.html new file mode 100644 index 000000000..482b93ac1 --- /dev/null +++ b/salesforce-ci-cd-setup-integration-email/index.html @@ -0,0 +1,7818 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Email notifications from Salesforce CI/CD - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Email

+ + + +

Email Integration

+

You can receive notifications on one or multiple e-mail addresses when sfdx-hardis events are happening:

+
    +
  • Deployment from a major branch to a major Salesforce org (ex: integration git branch to Integration Org)
  • +
  • Salesforce Org Monitoring
      +
    • Latest updates
    • +
    • Failing apex tests
    • +
    • Monitoring checks notifications
    • +
    +
  • +
+

Note: Salesforce email sending capabilities are used, so every email will count in your org daily email limit.

+

+

Configuration

+

Define CI/CD variable NOTIF_EMAIL_ADDRESS with the related email(s)

+

Examples:

+
    +
  • NOTIF_EMAIL_ADDRESS=admin@cloudity.com
  • +
  • NOTIF_EMAIL_ADDRESS=admin@cloudity.com,another.user@cloudity.com,nico@cloudity.com
  • +
+

Troubleshooting

+

If the emails are not sent, apply the following configuration on the Monitoring / Deployment user settings

+
    +
  • Send through Salesforce
  • +
+

+

That's all, you're all set !

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-generic-ticketing/index.html b/salesforce-ci-cd-setup-integration-generic-ticketing/index.html new file mode 100644 index 000000000..092b9e0df --- /dev/null +++ b/salesforce-ci-cd-setup-integration-generic-ticketing/index.html @@ -0,0 +1,7946 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Integrations between sfdx-hardis and any ticketing system - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Generic Ticketing

+ + + + +

Generic ticketing integration

+

If you use a ticketing system on your project, sfdx-hardis can use it to enrich its integrations

+

Sfdx-hardis will automatically analyze commits and PR/MR descriptions to collect tickets and build their urls !

+

+

Configuration

+

You need to define 2 environment variables in your CI/CD configuration

+

GENERIC_TICKETING_PROVIDER_REGEX

+

Regular expression allowing to detect your ticketing system identifiers in the commits / PR texts.

+

You can use https://regex101.com/ to check your Regular Expression.

+

Example: ([R|I][0-9]+-[0-9]+) to detect EasyVista references, that can look like I240103-0133 or +R230904-0026

+

GENERIC_TICKETING_PROVIDER_URL_BUILDER

+

Template string allowing to build a hyperlink from a ticket identifier.

+

Must contain a {REF} segment that will be replaced by the ticket identifier.

+

Example: https://instance.easyvista.com/index.php?ticket={REF}

+

Gitlab configuration

+

If you are using Gitlab, you need to update the Merge Request Settings

+

Go to Project -> Settings -> Merge Requests

+

Update Merge Commit Message Template with the following value

+
%{title} Merge branch '%{source_branch}' into '%{target_branch}'
+
+%{issues}
+
+See merge request %{reference}
+
+%{description}
+
+%{all_commits}
+
+

Update Squash Commit Message Template with the following value

+
%{title} Merge branch '%{source_branch}' into '%{target_branch}'
+
+%{issues}
+
+See merge request %{reference}
+
+%{description}
+
+%{all_commits}
+
+

Technical notes

+

This integration use the following variables, that must be available from the pipelines:

+
    +
  • GENERIC_TICKETING_PROVIDER_REGEX
  • +
  • GENERIC_TICKETING_PROVIDER_URL_BUILDER
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-github/index.html b/salesforce-ci-cd-setup-integration-github/index.html new file mode 100644 index 000000000..a07ca85ef --- /dev/null +++ b/salesforce-ci-cd-setup-integration-github/index.html @@ -0,0 +1,7769 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Integrations between sfdx-hardis and GitHub - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

GitHub

+ + + +

GitHub Pull Requests comments

+

In order to avoid to have to open job logs to see deployment errors, sfdx-hardis can post them as Comment on the Pull Request UI

+

To use this capability, all you need is to have permissions on your workflows and send your GITHUB_TOKEN (see full example)

+
    permissions:
+      pull-requests: write
+
+...
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        FORCE_COLOR: "1"
+
+

Everytime you will make a Pull Request, the CI job will post its result as comment !

+
    +
  • Example with deployment success
  • +
+

+
    +
  • Example with deployment errors
  • +
+

+

Notes:

+
    +
  • This integration works with sfdx-hardis pipeline, but also on home-made pipelines, just call sf hardis:project:deploy:start instead of sf project:deploy:start !
  • +
+
    +
  • +

    This integration use the following variables:

    +
      +
    • GITHUB_TOKEN (provided by GitHub but has to be send as option to the deployment jobs)
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-gitlab/index.html b/salesforce-ci-cd-setup-integration-gitlab/index.html new file mode 100644 index 000000000..895074c76 --- /dev/null +++ b/salesforce-ci-cd-setup-integration-gitlab/index.html @@ -0,0 +1,7773 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Integrations between sfdx-hardis and Gitlab - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Gitlab

+ + + +

Gitlab Merge request notes

+

In order to avoid to have to open job logs to see deployment errors, sfdx-hardis can post them as Notes on the Merge Request UI

+

To use this capability:

+
    +
  • Go to Settings -> Access Tokens -> Create a project access token with level Developer and scope api, and name it SFDX HARDIS BOT
  • +
+

image

+
    +
  • Go to Settings -> CI/CD -> Variables -> Create a variable named CI_SFDX_HARDIS_GITLAB_TOKEN and past the access token value
  • +
+

image

+

Everytime you will make a merge request, the CI job will post its result as comment !

+
    +
  • Example with deployment errors
  • +
+

+
    +
  • Example with failing test classes
  • +
+

+

Notes:

+
    +
  • This integration works with sfdx-hardis pipeline, but also on home-made pipelines, just call sf hardis:project:deploy:start instead of sf project:deploy:start !
  • +
+
    +
  • This integration use the following variables:
      +
    • CI_SFDX_HARDIS_GITLAB_TOKEN
    • +
    • CI_SERVER_URL (provided by Gitlab CI)
    • +
    • CI_PROJECT_ID (provided by Gitlab CI)
    • +
    • CI_MERGE_REQUEST_IID (provided by Gitlab CI)
    • +
    • CI_JOB_NAME (provided by Gitlab CI)
    • +
    • CI_JOB_URL (provided by Gitlab CI)
    • +
    • GITLAB_API_REJECT_UNAUTHORIZED: set to "false" if you want to allow connection even without certificate (can be useful on on-premise GitLab instance)
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-jira/index.html b/salesforce-ci-cd-setup-integration-jira/index.html new file mode 100644 index 000000000..18fb892cf --- /dev/null +++ b/salesforce-ci-cd-setup-integration-jira/index.html @@ -0,0 +1,8105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Integrations between sfdx-hardis and Jira - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Jira

+ + + + +

Jira integration

+

If you use JIRA on your project, sfdx-hardis can use it to enrich its integrations

+

Sfdx-hardis will automatically analyze commits and PR/MR descriptions to collect JIRA tickets URLS !

+

You can use the full URL of JIRA tickets in your commits and PR/MR descriptions.

+
+

Use https://sfdx-hardis.atlassian.net/browse/CLOUDITY-4 , not CLOUDITY-4 !

+
+

If you don't use full URL, a default expression will be used, that you can override for a better accuracy (see Identify JIRA Tickets )

+
+

In that case, CLOUDITY-4 will be detected, but make sure that JIRA_HOST is defined

+
+

For git providers

+

Github, Gitlab, Azure, Bitbucket: Post references to JIRA tickets in PR/MR comments

+

+

For notifications providers

+

Slack, MsTeams: Add deployed JIRA tickets in deployment notifications

+

+

Update JIRA issues

+

Add comments and tags on JIRA tickets when they are deployed in a major org

+

Default tag is UPPERCASE(branch_name) + "_DEPLOYED".

+

To override it, define env variable DEPLOYED_TAG_TEMPLATE, that must contain {BRANCH}.

+

Example: DEPLOYED_TO_{BRANCH}

+

+

Global configuration

+

Identify JIRA Tickets

+

Define CI/CD variable JIRA_TICKET_REGEX with a regular expression allowing to identify the JIRA tickets of your project in commit& Pull Requests titles & bodies, for example (CLOUDITY-[0-9]+)

+

Jira Cloud

+

Define CI/CD variables

+
    +
  • JIRA_HOST (example: https://sfdx-hardis.atlassian.net/)
  • +
  • JIRA_EMAIL (example: nicolas.vuillamy@cloudity.com)
  • +
  • JIRA_TOKEN , to create following Atlassian documentation
  • +
+

Jira On-Premise

+

Note: Does not seems to work with every on-premise JIRA servers

+

Define CI/CD variables

+
    +
  • JIRA_HOST (examples: https://jira.cloudity.com/ , or with path like https://pid.cloudity.com/jira/)
  • +
  • JIRA_PAT, to create following Atlassian Documentation (section Creating PATs in the application)
  • +
+

Gitlab configuration

+

If you are using Gitlab, you need to update the Merge Request Settings

+

Go to Project -> Settings -> Merge Requests

+

Update Merge Commit Message Template with the following value

+
%{title} Merge branch '%{source_branch}' into '%{target_branch}'
+
+%{issues}
+
+See merge request %{reference}
+
+%{description}
+
+%{all_commits}
+
+

Update Squash Commit Message Template with the following value

+
%{title} Merge branch '%{source_branch}' into '%{target_branch}'
+
+%{issues}
+
+See merge request %{reference}
+
+%{description}
+
+%{all_commits}
+
+

Technical notes

+

This integration use the following variables, that must be available from the pipelines:

+
    +
  • JIRA_HOST
  • +
  • JIRA_EMAIL
  • +
  • JIRA_TOKEN
  • +
  • JIRA_PAT
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-ms-teams/index.html b/salesforce-ci-cd-setup-integration-ms-teams/index.html new file mode 100644 index 000000000..cfef7e314 --- /dev/null +++ b/salesforce-ci-cd-setup-integration-ms-teams/index.html @@ -0,0 +1,7789 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Microsoft Teams notifications from Salesforce CI/CD - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Microsoft Teams

+ + + +

Ms Teams Integration

+

MS Teams Web Hooks have been deprecated my Microsoft so have been removed from sfdx-hardis.

+

Instead, please use Email Notifications with the Ms Teams Channel Email as NOTIF_EMAIL_ADDRESS

+

To get MsTeams email channel, click on the channel contextual menu, then "Get channel E-mail Address"

+

+

Then make sure that anyone can send emails to the channel by selecting the first option

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integration-slack/index.html b/salesforce-ci-cd-setup-integration-slack/index.html new file mode 100644 index 000000000..411b74cb8 --- /dev/null +++ b/salesforce-ci-cd-setup-integration-slack/index.html @@ -0,0 +1,7975 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Integrations between sfdx-hardis and Slack - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Slack

+ + + +

sfdx-hardis-slack-logo

+

Slack Integration

+

You can receive notifications on slack channels when sfdx-hardis events are happening:

+
    +
  • Deployment from a major branch to a major Salesforce org (ex: integration git branch to Integration Org)
  • +
  • Salesforce Org Monitoring
      +
    • Latest updates
    • +
    • Failing apex tests
    • +
    • Monitoring checks notifications
    • +
    +
  • +
+

slack-notifs

+

Configure Slack Application

+

All the following steps are summarized in this video tutorial

+
+ +

Create slack app

+
+

Process only if a sfdx-hardis bot has not yet been configured on your slack. Otherwise, just request the slack token value to your slack administrator

+
+

Create a slack app here -> https://api.slack.com/apps

+
    +
  • Name it sfdx-hardis bot or any nickname you like, like your guinea pig name !
  • +
  • Go to permissions and add the following scopes
      +
    • chat-write
    • +
    • chat-write.customize
    • +
    • chat-write.public
    • +
    +
  • +
  • Create auth token and copy its values
  • +
+

Configure sfdx-hardis for slack

+
    +
  • Create a secret value named SLACK_TOKEN with auth token value in your Git provider configuration
  • +
+
    +
  • Create a slack channel that will receive all notifications (ex: #notifs-sfdx-hardis)
  • +
+
    +
  • Open the channel info, copy its ID and create a secret value named SLACK_CHANNEL_ID in your git provider configuration
  • +
+
    +
  • Invite the sfdx-hardis bot user to the channel (ex: /invite @sfdx-hardis-bot)
  • +
+
    +
  • Additionally, you can create branch-scoped channels by creating new channels and create appropriate variables
      +
    • Example: Channel #notifs-sfdx-hardis-integration and variable SLACK_CHANNEL_ID_INTEGRATION
    • +
    +
  • +
+
    +
  • You can also define an additional channel to receive only warning, error and critical notifications in another channel
      +
    • Example: Channel #notifs-monitor-hot and variable SLACK_CHANNEL_ID_ERRORS_WARNINGS
    • +
    +
  • +
+
    +
  • Make sure all those variables are visible to your CI/CD pipelines
  • +
+

That's all, you're all set !

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-integrations-home/index.html b/salesforce-ci-cd-setup-integrations-home/index.html new file mode 100644 index 000000000..27297f044 --- /dev/null +++ b/salesforce-ci-cd-setup-integrations-home/index.html @@ -0,0 +1,7873 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Integrations between sfdx-hardis and external tools - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Integrations Home

+ + + +

+

Every info that sfdx-hardis can provide is available in log files or console terminals.

+

In order to enhance the user experience, integrations with external tools must be configured.

+

Git Providers

+

Depending of your git provider, configure one of the following integrations.

+
    +
  • GitHub
      +
    • Deployment status in Merge Request notes
    • +
    • Quick Deploy to enhance performances
    • +
    +
  • +
+
    +
  • Gitlab
      +
    • Deployment status in Merge Request notes
    • +
    • Quick Deploy to enhance performances
    • +
    +
  • +
+
    +
  • Azure Pipelines
      +
    • Deployment status in Pull Request threads
    • +
    • Quick Deploy to enhance performances
    • +
    +
  • +
+
    +
  • BitBucket
      +
    • Deployment status in Pull Request comments
    • +
    • Quick Deploy to enhance performance
    • +
    +
  • +
+

Message notifications

+
    +
  • Slack
      +
    • Notifications
    • +
    +
  • +
+ +
    +
  • Email
      +
    • Notifications
    • +
    +
  • +
+ +

Ticketing providers

+
    +
  • Jira
      +
    • Enrich MR/PR comments by adding tickets references and links
    • +
    • Enrich notifications comments by adding tickets references and links
    • +
    • Post a comment and a label on JIRA issues when they are deployed in a major org
    • +
    +
  • +
+
    +
  • Azure Boards
      +
    • Enrich MR/PR comments by adding work items references and links
    • +
    • Enrich notifications comments by adding work items references and links
    • +
    • Post a comment and a tag on Azure Work Items when they are deployed in a major org
    • +
    +
  • +
+
    +
  • Generic ticketing
      +
    • Enrich MR/PR comments by adding tickets references and links
    • +
    • Enrich notifications comments by adding tickets references and links
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-setup-merge-request/index.html b/salesforce-ci-cd-setup-merge-request/index.html new file mode 100644 index 000000000..81489b36d --- /dev/null +++ b/salesforce-ci-cd-setup-merge-request/index.html @@ -0,0 +1,7758 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + First merge request - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

First merge request

+ + + + +

Initialization merge request

+

Create your first merge request with branch cicd as source, and your lower major branch as target (usually integration)

+

Make sure that before merging your first merge request, file manifest/destructiveChange.xml is empty

+

You will see errors, but it is normal: Follow Maintainer Guide to complete your configuration !

+

Once all controlling jobs are in success, your CI/CD setup is completed !

+

Common issues

+

Translations

+

If you removed Dashboards and reports from the repo, their translations can remain in files like translations/en_US.xml

+

Remove all related XML blocks as they contain unused translations.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-solve-deployment-errors/index.html b/salesforce-ci-cd-solve-deployment-errors/index.html new file mode 100644 index 000000000..8bd862e6e --- /dev/null +++ b/salesforce-ci-cd-solve-deployment-errors/index.html @@ -0,0 +1,7838 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Solve Salesforce deployment errors - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ + + + + + + +

Solve deployment errors

+ + + + +

Metadata errors

+

sfdx-hardis will display the error and often provide tips about how to solve the error.

+

+

Fix with new commit

+

You can solve the issue, create a new commit and run again command

+

Fix with reset commits then new commit

+

If the issue is caused by the fact that you committed files that you finally decided to not publish, you can reset your selection.

+
    +
  • Click on : that will rollback all the previous commits of your current git branch
  • +
+
    +
  • Stage and commit again the elements that you want to publish
  • +
+
    +
  • Run command
  • +
+

Test classes errors

+

+

That's simple: fix the test classes :)

+

If you are an admin, you might need the help of a developer, who will directly work in your branch

+

Code Coverage errors

+

Don't be lazy, write the missing test classes :)

+

You know you'll need them to be able to deploy in production anyway :)

+

SOS, I'm lost

+ + + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-solve-megalinter-errors/index.html b/salesforce-ci-cd-solve-megalinter-errors/index.html new file mode 100644 index 000000000..64fa2ad65 --- /dev/null +++ b/salesforce-ci-cd-solve-megalinter-errors/index.html @@ -0,0 +1,7813 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Solve Salesforce MegaLinter errors - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Solve MegaLinter errors

+ + + + +

Apex best practices using PMD

+

You don't want technical debt on your project !

+

Download job artifacts that will contain a file sfdx-scanner-report-apex.csv.

+

+

Open the file to see the errors

+

+
    +
  • If the errors are in code that has been written by a developer, solve it
  • +
+
    +
  • If the errors are from imported or generated classes, you can bypass them by adding annotation @SuppressWarnings('PMD') at the top of the classes
  • +
+
    +
  • // NOPMD at the end of a line will make an issue ignored, but again use it only in case of false positive, never to "Publish more quickly", else you'll create technical debt.
      +
    • If you use // NOPMD, specify why as comment . Example: // NOPMD Strings already escaped before
    • +
    +
  • +
+

LWC best practices using eslint

+

sfdx-scanner-lwc embedded in MegaLinter is hard to use.

+

If you don't succeed, you can define SALESFORCE_SFDX_SCANNER_LWC in DISABLE_LINTERS property in .mega-linter.yml config file.

+

Security issues

+

Solve the security issues if they are critical like hardcoded tokens, or bypass the linters (release manager action only)

+

Excessive copy-pastes

+

Refactor your code to avoid excessive copy-pastes !

+

You can also add exceptions in .jscpd.json file, but really in case it has sense, not out of laziness

+

Example of .mega-linter.yml config file

+
# Extend from shared sfdx-hardis Mega-Linter configuration :)
+EXTENDS:
+  - https://raw.githubusercontent.com/hardisgroupcom/sfdx-hardis/main/config/sfdx-hardis.mega-linter-config.yml
+
+DISABLE_LINTERS:
+- SALESFORCE_SFDX_SCANNER_LWC
+- SALESFORCE_SFDX_SCANNER_AURA
+- CSS_STYLELINT
+
+SALESFORCE_SFDX_SCANNER_APEX_DISABLE_ERRORS_IF_LESS_THAN: 6 # ONLY THE RELEASE MANAGER CAN UPDATE THIS VALUE !
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-use-home/index.html b/salesforce-ci-cd-use-home/index.html new file mode 100644 index 000000000..205f1690e --- /dev/null +++ b/salesforce-ci-cd-use-home/index.html @@ -0,0 +1,7734 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Salesforce CI/CD Contributor Guide - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Contributor Guide Home

+ + + + +
+

Initialization

+

You need a stack of applications and to have Salesforce sources on your computer to be able to start to work on a CI/CD project.

+ +
+

Make updates on your Salesforce project

+

Now your computer is ready, let's see how you can use sandboxes or scratch orgs to make updates in your Salesforce projects !

+ +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-use-install/index.html b/salesforce-ci-cd-use-install/index.html new file mode 100644 index 000000000..6f6459198 --- /dev/null +++ b/salesforce-ci-cd-use-install/index.html @@ -0,0 +1,7738 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Salesforce CI/CD Installation User guide - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Prepare your computer

+ + + +

Computer Installation user guide

+
+

If you installed Salesforce DX or Salesforce CLI using Windows installer, please uninstall it using Windows -> Programs > Uninstall

+
+

See tutorial

+
+ + +
    +
  • Install VsCode extension VsCode SFDX Hardis by searching for Hardis is VsCode extensions plugin pane.
  • +
+
    +
  • Once installed, click on Hardis Group button in VsCode left bar
  • +
+
    +
  • Messages will appear at the bottom right of VsCode and ask you to install additional applications and activate settings. Follow all of them until there is none left.
      +
    • When later you'll see such messages again from sfdx-hardis, click to apply them to upgrade applications.
    • +
    +
  • +
+

+
    +
  • When no warning in displayed in the dependencies panel, you're all set !
  • +
+

+
+

Under the hood Under the hood

+

The installed applications are the following:

+ +
+

Now your computer is all set, you can clone your project git repository :)

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-validate-merge-request/index.html b/salesforce-ci-cd-validate-merge-request/index.html new file mode 100644 index 000000000..0b7343f99 --- /dev/null +++ b/salesforce-ci-cd-validate-merge-request/index.html @@ -0,0 +1,7910 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Validate a merge request on a Salesforce CI/CD project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Validate a merge request

+ + + + +
+

Conflicts

+

This section must be managed by team members with git knowledge

+

If elements has been modified in another branch, you need to manage conflicts before being able to merge.

+
    +
  • Merge conflicts then commit and push your updates, it will trigger again the control job with the new branch state.
  • +
+

This video shows how to merge conflicts with Visual Studio Code.

+
+ +

In case conflicts are too complicated to manage (like on a Flow for example), you need to:

+
    +
  • Retrofit the new version of the flow in your branch (that will overwrite your updates)
  • +
  • Sfdx Push it to your source-tracked sandbox or scratch org
  • +
  • Make again the updates in the Salesforce Setup
  • +
  • Sfdx Pull the updated version in your local branch
  • +
  • Git Commit & Push to your branch
  • +
+
+

Control jobs

+

Each merge request runs automatically the control jobs that will insure that the future deployment with be valid.

+
+

Check deploy job

+

See Handle Deployment errors

+
+

Code Quality job

+

See Handle MegaLinter errors

+
+

Merge

+

Depending on the project organization, this action can be allowed only to Release managers, or to more team members

+

If there are no conflicts and if all control jobs are in success, you can proceed to the merge of the merge request.

+
+

Pre deployment actions

+

If pre-deployment actions are required, perform them before clicking on the button to merge the Merge Request / Pull Request

+

Pre-deployment actions can usually be found in README.md

+

IMPORTANT: If Custom Profiles are deployed for the first time, you MUST create them manually in target org, by cloning them from "Minimal access" Profile

+
+

Effective merge

+
    +
  • Click on Merge
      +
    • If the merge request is from a minor branch (dev or config task), make sure that Squash commits and Delete after merge are checked
    • +
    • If the merge request if from a major branch (develop, recette, uat, preprod...), make sure that Squash commits and Delete after merge are NOT checked
    • +
    +
  • +
+
    +
  • The merge commit in the target branch will trigger a new job that will automatically deploy the updated source to the corresponding Salesforce org
  • +
+
+

Post deployment actions

+

If post-deployment actions are required, perform them before clicking on the button to merge the Merge Request / Pull Request

+

Post-deployment actions can usually be found in README.md

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-work-on-task-configuration/index.html b/salesforce-ci-cd-work-on-task-configuration/index.html new file mode 100644 index 000000000..2f085955e --- /dev/null +++ b/salesforce-ci-cd-work-on-task-configuration/index.html @@ -0,0 +1,7871 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Perform configuration in your Salesforce org - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Configure Salesforce

+ + + + +

Configuration

+

Please follow as much as possible these recommendations when you work on a CI/CD Salesforce project, otherwise it will generate more release management charges and risks of regressions.

+

Api names

+
    +
  • Do not rename API names (field names, picklist values, pages...)
  • +
+
    +
  • Do not prefix API Names with numbers: Git provides historization of updates, so it's better to have elements sorted by alphabetical order than by order of creation
  • +
+
    +
  • Do not change the type of custom fields: It forces the release manager to perform manual actions
  • +
+

Access management

+
    +
  • Always use Permission Sets instead of Profiles. If you need profiles, discuss with your release manager.
  • +
+
    +
  • If you create a Custom Profile, please notify your release manager.
      +
    • Before the first deployment, this Profile must be created manually in the target org by cloning "Minimum access" Profile
    • +
    +
  • +
+

Flows

+
    +
  • If you need to update Flows, discuss to make sure that no other member of the team is updating the same Flow in another branch/org
      +
    • If it happens, conflicts are not manageable so one of you will later need to perform the updates again
    • +
    +
  • +
+

Hardcoded Ids

+
    +
  • Never use hardcoded Ids in Flows and Formulas (or anywhere else)
  • +
+

Images

+
    +
  • Use static resources or content assets to store images
  • +
+

User references

+
    +
  • Do not use direct references to users, use Public Groups instead
  • +
+
    +
  • Share your reports and email templates with public groups, not named users.
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-work-on-task-development/index.html b/salesforce-ci-cd-work-on-task-development/index.html new file mode 100644 index 000000000..e40fde02b --- /dev/null +++ b/salesforce-ci-cd-work-on-task-development/index.html @@ -0,0 +1,7756 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Develop on a Salesforce DX project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Develop in Salesforce

+ + + +

Salesforce Development

+

Update code & XML Metadatas

+
    +
  • You can update code and XML metadatas using VsCode IDE
  • +
  • When you need to upload the updates to your org, use command Push to org button
  • +
  • If you made updates directly on your org, use command Pull from org button to retrieve into local files the updates that you performed online with point & click
  • +
  • Once you have finished, you can publish your task
  • +
+

Recommendations

+
    +
  • Use Visual Studio code editor to update code (online Developer Console is not recommended)
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-work-on-task-install-packages/index.html b/salesforce-ci-cd-work-on-task-install-packages/index.html new file mode 100644 index 000000000..02c65da04 --- /dev/null +++ b/salesforce-ci-cd-work-on-task-install-packages/index.html @@ -0,0 +1,7705 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Install packages on your org - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Install packages

+ + + +

Install packages

+
+

Packages (managed or not) must never be directly installed in a major org (integration, uat, preprod, production), it has to be done in dev sandbox / scratch orgs

+
+

If you can find the package id (starting by 04T), use sfdx-hardis command Install package button to install package instead of installing them directly with the URL

+

If you installed a package using an URL, use command Retrieve packages button to retrieve package config before creating your merge request (be careful of what you commit in .sfdx-hardis.yml file !)

+
+

Once packages are referenced in .sfdx-hardis.yml, they will automatically be installed on major orgs during CI/CD deployments

+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-work-on-task-open-org/index.html b/salesforce-ci-cd-work-on-task-open-org/index.html new file mode 100644 index 000000000..228d30d20 --- /dev/null +++ b/salesforce-ci-cd-work-on-task-open-org/index.html @@ -0,0 +1,7708 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Open your Salesforce org - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Open your org

+ + + +

Open your org

+

You can use Salesforce Setup to configure your org as you would do on any sandbox.

+
    +
  • Open your Salesforce DX project with Visual Studio Code
  • +
  • Open VsCode SFDX Hardis extension by clicking on Hardis Group button in VsCode left bar (loading can task several seconds)
  • +
  • Click on Open current org button to open your org in browser
      +
    • If you want to use another org, use menu Select org button to select another one
    • +
    +
  • +
  • Perform your configurations in the org
  • +
  • Once you have finished, you can publish your task
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-work-on-task-profiles/index.html b/salesforce-ci-cd-work-on-task-profiles/index.html new file mode 100644 index 000000000..0ce836957 --- /dev/null +++ b/salesforce-ci-cd-work-on-task-profiles/index.html @@ -0,0 +1,7762 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Handle Profiles on a Salesforce CI/CD project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Handle Profiles

+ + + +

Deploy Profiles

+

Use Permission Sets

+

In case an attribute is available on Profiles and Permission Sets: USE PERMISSION SETS :)

+
    +
  • Apex Class Access (classAccesses)
  • +
  • Custom Metadata Type Access (customMetadataTypeAccesses)
  • +
  • External Data Source Access (externalDataSourceAccesses)
  • +
  • Field Permissions (fieldPermissions)
  • +
  • Object Permissions (objectPermissions)
  • +
  • Page Access (pageAccesses)
  • +
  • User Permissions (userPermissions (except on Admin Profile))
  • +
+

If you are on a build project, it is recommended to automate Minimize Profile so such attributes are automatically removed from Profiles before Merge Requests.

+

Tab visibility

+

When you retrieve a profile, standard tabs visibility is not present in the XML.

+

This is quite boring because if you do nothing, Calendar, Tasks, Home or Contact tab visibilities won't be deployed !

+

To avoid that, standard tab visibility must be added in the Profile XML.

+

You can use sfdx-hardis command Fix Profile Tabs to Show / Hide tabs in your Profile XML files.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-ci-cd-work-on-task/index.html b/salesforce-ci-cd-work-on-task/index.html new file mode 100644 index 000000000..a26178b7d --- /dev/null +++ b/salesforce-ci-cd-work-on-task/index.html @@ -0,0 +1,7707 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Work on a task on a Salesforce DX project - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ +
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-deployment-assistant-error-list/index.html b/salesforce-deployment-assistant-error-list/index.html new file mode 100644 index 000000000..b8e7708fc --- /dev/null +++ b/salesforce-deployment-assistant-error-list/index.html @@ -0,0 +1,10131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sfdx-hardis deployment assistant list of errors - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + +

Salesforce deployment assistant errors list

+

sfdx-hardis can help solve solve deployment errors using a predefined list of issues and associated solutions

+

See how to setup sfdx-hardis deployment assistant

+

If you see a deployment error which is not here yet, please add it in this file :)

+

API Version error

+

Detection

+
    +
  • RegExp: Error (.*) The (.*) apiVersion can't be "([0-9]+)"
  • +
+

Resolution

+
{1} metadata has probably been created/updated in a sandbox already upgraded to next platform version (ex: Sandbox in Summer'23 and Production in Spring'23)
+- First, try to update the api version in the XML of {1} metadata file (decrement the number in <apiVersion>{3}.0</apiVersion>)
+- If it still doesn't work because the metadata structure has changed between version, you may try a sf project:retrieve:start of the metadata by forcing --api-version at the end of the command.
+
+
+

Allow deployment with pending Apex Jobs

+

Detection

+
    +
  • String: You can bypass this error by allowing deployments with Apex jobs in the Deployment Settings page in Setup.
  • +
+

Resolution

+
Go to target org, in Setup -> Deployment Settings -> Activate option "Allow deployments of components when corresponding Apex jobs are pending or in progress."
+
+
+

Can not change field type to a formula field

+

Detection

+
    +
  • RegExp: Error (.*) Cannot update a field from a Formula to something else
  • +
+

Resolution

+
You need to manually delete or rename the field in the target org to allow the deployment to pass
+- First, try to manually delete field {1} in the target org
+- if you can't delete {1}, rename it into {1}_ToDel, then once the deployment done, delete {1}_ToDel
+
+
+

Can not change type due to existing data

+

Detection

+
    +
  • RegExp: Error (.*) Cannot change type due to existing data
  • +
+

Resolution

+
It is usually not recommended to change types of fields, but if it's really necessary you can:
+- Manually change the type of {1} in the target org
+- If you can't manually change the type:
+  - you may modify the dependencies (Formulas, Flows...) using {1}, so they don't use this field
+  - you can also delete dependencies (Formulas, Flows...) using {1}, but make sure they are deployed again later
+- More help: https://help.salesforce.com/s/articleView?id=000327186&type=1
+
+
+

Can not change field type with picklist

+

Detection

+
    +
  • RegExp: Error (.*) Cannot change which global value set this picklist uses
  • +
+

Resolution

+
You probably updated the type of field {1}, and Salesforce does not allows that with deployments. You can:
+- Try to manually change the type of {1} directly in target org, but it may not be technically possible
+- Delete field {1} in target org: it will be recreated after deployment (but you will loose data on existing records, so be careful if your target is a production org)
+- Create another field with desired type and manage data recovery if the target is a production org
+
+
+

Can not delete custom field

+

Detection

+
    +
  • RegExp: This (.*) is referenced elsewhere in salesforce.com
  • +
  • RegExp: Le champ personnalisé (.*) est utilisé dans (.*)
  • +
+

Resolution

+
Custom field {1} can not be deleted because it is used elsewhere. Remove its references ans try again
+THIS MAY BE A FALSE POSITIVE if you are just testing the deployment, as destructiveChanges are deployed separately from updated items deployment check
+
+
+

Can not delete record type

+

Detection

+
    +
  • RegExp: Error (.*) Cannot delete record type through API
  • +
+

Resolution

+
You need to manually delete record type {1} in target org
+- Edit record type {1}, uncheck "Active"
+- Delete record type {1}
+
+
+

Can not find folder

+

Detection

+
    +
  • RegExp: Error (.*) Cannot find folder:(.*)
  • +
+

Resolution

+
Folder {2} is missing.
+- If folder {2} is existing in sources, add it in related package.xml
+- If folder {2} is not existing in DX sources, please use sf hardis:project:clean:retrievefolders to retrieve it
+- If both previous solutions did not work, go create manually folder {2} in target org
+
+
+

Can not find user

+

Detection

+
    +
  • RegExp: Error (.*) Cannot find a user that matches any of the following usernames
  • +
+

Resolution

+
You made reference to username(s) in {1}, and those users probably do not exist in target org.
+- Do not use named users, but user public groups for assignments -> https://help.salesforce.com/s/articleView?id=sf.creating_and_editing_groups.htm&type=5
+- or Create matching user(s) in the target deployment org
+- or Remove the XML part referring to hardcoded usernames
+
+Example of XML you have to remove in {1}:
+
+<folderShares>
+  <accessLevel>Manage</accessLevel>
+  <sharedTo>nicolas.vuillamy@hardis-scratch-po-tgci-root-develop_20220412_0604.com</sharedTo>
+  <sharedToType>User</sharedToType>
+</folderShares>
+
+
+

Can not find user (2)

+

Detection

+
    +
  • RegExp: Error (.*) In field: (.*) - no User named (.*) found
  • +
+

Resolution

+
You made reference to username {3} in {1}, and it probably does not exist in the target org.
+- Do not use named users, but user public groups for assignments -> https://help.salesforce.com/s/articleView?id=sf.creating_and_editing_groups.htm&type=5
+- or Create matching user {3} in the target deployment org
+- or open {1} metadata and remove the XML part referring to hardcoded username {3}
+
+
+

Cannot update a field to a Summary from something else

+

Detection

+
    +
  • RegExp: Error (.*) Cannot update a field to a (.*) from something else
  • +
+

Resolution

+
You probably updated the type of field {1} to type {2}, and Salesforce does not allows that with deployments. You can:
+- Try to manually change the type of {1} directly in target org, but it may not be technically possible
+- Delete field {1} in target org: it will be recreated after deployment (but you will loose data on existing records, so be careful if your target is a production org)
+- Create another field with desired type and manage data recovery if the target is a production org
+
+
+

Change Matching Rule

+

Detection

+
    +
  • RegExp: Error (.*) Before you change a matching rule, you must deactivate it
  • +
+

Resolution

+
To be able to deploy, you must go in target org setup to manually deactivate matching rule {1}
+
+
+

Condition missing reference

+

Detection

+
    +
  • RegExp: Error (.*) field integrity exception: unknown \(A condition has a reference to (.*), which doesn't exist.\)
  • +
+

Resolution

+
There is a reference to {2} in {1}, and {2} is not found. You can either:
+- Add {2} in your deployment sources and make sure it is named in package.xml
+- Remove the reference to {2} in {1}
+
+
+

Couldn't retrieve or load information on the field

+

Detection

+
    +
  • RegExp: Error (.*) Something went wrong. We couldn't retrieve or load the information on the field: (.*)\.
  • +
+

Resolution

+
There is a reference to {2} in {1}, and {2} is not found. You can either:
+- Commit {2} in your deployment sources and make sure it is named in package.xml
+- Remove the reference to {2} in {1}
+
+
+

Custom object not found

+

Detection

+
    +
  • RegExp: Error (.*) In field: field - no CustomObject named (.*) found
  • +
+

Resolution

+
A reference to a custom object {2} is not found in {1}:
+- If you renamed the custom object, do a search/replace in sources with previous object name and new object name
+- If you deleted the custom object, or if you don't want to deploy it, do a search on the custom object name, and remove XML elements referencing it
+- If the object should exist, make sure it is in force-app/main/default/objects and that the object name is in manifest/package.xml in CustomObject section
+You may also have a look to command sf hardis:project:clean:references
+
+
+

Custom field not found

+

Detection

+
    +
  • RegExp: Error (.*) In field: (.*) - no CustomField named (.*)\.(.*) found
  • +
+

Examples

+
    +
  • Error PS_Admin In field: field - no CustomField named User.expcloud__Portal_Username__c found
  • +
+

Resolution

+
A reference to a custom field {3}.{4} is not found in {1}:
+- If you renamed {3}.{4}, do a search/replace in {1} with previous field name and {4}
+- If you deleted {3}.{4}, or if you don't want to deploy it, do a search on {4} in all sources, and remove all XML elements referring to {3}.{4} (except in destructiveChanges.xml)
+- If {3}.{4} should exist, make sure it is in force-app/main/default/objects/{3}/fields and that {3}.{4} is in manifest/package.xml in CustomField section
+- If {3}.{4} is standard, the error is because {3}.{4} is not available in the org you are trying to deploy to. You can:
+  - Remove the reference to {4} in the XML of {1} ( maybe sf hardis:project:clean:references can clean automatically for you ! )
+  - Activate the required features/license in the target org
+
+
+

Mandatory custom field can not be in a profile/permission set

+

Detection

+
    +
  • RegExp: Error (.*) You cannot deploy to a required field: (.*)
  • +
+

Resolution

+
- Search for {2} in source file XML of {1}, then remove the entries matching the results
+Example of element to delete:
+<fieldPermissions>
+  <editable>true</editable>
+  <field>{2}</field>
+  <readable>true</readable>
+</fieldPermissions>
+
+
+

Custom metadata entry not found

+

Detection

+
    +
  • RegExp: Error (.*) In field: (.*) - no CustomMetadata named (.*) found
  • +
+

Resolution

+
A reference to a custom metadata {3} of type {2} is not found in {1}:
+- Are you sure you deployed {3} ?
+- If you use a package.xml, is {3} present within type CustomMetadata ?
+
+
+

Expired Access / Refresh Token

+

Detection

+
    +
  • String: expired access/refresh token
  • +
+

Resolution

+
Run command "Select another org" from Status panel (or sf hardis:org:select) to authenticate again to your org
+
+
+

Missing Data Category Group

+

Detection

+
    +
  • RegExp: Error (.*) In field: DeveloperName - no DataCategoryGroup named (.*) found
  • +
+

Resolution

+
If Data Category Group {2} is not existing yet in target org, you might need to:
+- create it manually in target org before deployment
+- comment DataCategoryGroup in {1} XML
+
+
+

Dependent class is invalid and needs recompilation

+

Detection

+
    +
  • RegExp: Error (.*) Dependent class is invalid and needs recompilation
  • +
+

Resolution

+
Solve the other errors and this one will disappear !
+
+
+

Duplicate value Platform Action Id List

+

Detection

+
    +
  • String: duplicate value found: PlatformActionListId duplicates value on record with id
  • +
+

Resolution

+
There are probably issue with conflict management. Open the XML of the source item, and replace all <sortOrder> numbers to make an ascending order, starting with 0
+
+
+

Duplicate label

+

Detection

+
    +
  • RegExp: Error (.*) Duplicate label: (.*)
  • +
+

Resolution

+
You probably renamed the picklist API name for {2}. Please update manually the picklist {1} in the target org to avoid to have a duplicate label
+
+
+

Missing e-mail template

+

Detection

+
    +
  • RegExp: In field: template - no EmailTemplate named (.*) found
  • +
+

Resolution

+
An email template should be present in the sources. To retrieve it, you can run:
+sf project retrieve start -m EmailTemplate:{1} -o YOUR_ORG_USERNAME
+
+
+

Empty source items

+

Detection

+
    +
  • String: Required field is missing: sharingOwnerRules
  • +
  • String: Required field is missing: standardValue
  • +
  • String: Required field is missing: valueTranslation
  • +
+

Resolution

+
You probably retrieved empty items, that must not be included within the SFDX project
+To remove them, please run sfdx:hardis:project:clean:emptyitems
+
+
+

Enable CRM Analytics

+

Detection

+
    +
  • String: It should be created by enabling the CRM Analytics Cloud preference
  • +
+

Resolution

+
You must enable CRM Analytics (ex Wave, Einstein Analytics & Tableau CRM) in the target org.
+You probably also need to add CRM Analytics Admin Permission Set assignment to the deployment user
+
+
+

Error parsing file

+

Detection

+
    +
  • RegExp: Error (.*) Error parsing file: (.*)
  • +
+

Resolution

+
There has been an error parsing the XML file of {1}: {2}
+- Open file {1} and look where the error can be ! (merge issue, typo, XML tag not closed...)
+
+
+

Formula picklist field issue

+

Detection

+
    +
  • RegExp: Field:(.*) must not be Required
  • +
+

Resolution

+
You probably made read only field {1} that was required before.
+Find field {1} in the layout source XML, then replace Required by Readonly
+
+
+

Field not available for element

+

Detection

+
    +
  • RegExp: Field (.*) is not available for
  • +
+

Resolution

+
You probably changed the type of field {1}.
+Find field {1} in the source XML, and remove the section using it
+
+
+

Formula picklist field issue

+

Detection

+
    +
  • String: Les champs de liste de sélection sont pris en charge uniquement dans certaines fonctions.
  • +
+

Resolution

+
You probably changed the type of a field that is used in a formula.
+Update the formula to use a field compliant with formulas.
+More details at https://help.salesforce.com/articleView?id=sf.tips_on_building_formulas.htm&type=5
+
+
+

Flow must be deleted manually

+

Detection

+
    +
  • RegExp: .flow (.*) insufficient access rights on cross-reference id
  • +
+

Resolution

+
Flow {1} can not be deleted using deployments, please delete it manually in the target org using menu Setup -> Flows , context menu on {1} -> View details and versions -> Deactivate all versions -> Delete flow
+
+
+

Insufficient access rights on cross-reference id

+

Detection

+
    +
  • RegExp: Error (.*) insufficient access rights on cross-reference id
  • +
+

Resolution

+
- If {1} is a Flow, it can not be deleted using deployments, please delete it manually in the target org using menu Setup -> Flows , context menu on {1} -> View details and versions -> Deactivate all versions -> Delete flow
+- If you changed a custom field from unique to not unique, you need to manually make the change in the target org
+
+
+

Invalid formula grouping context

+

Detection

+
    +
  • String: Invalid custom summary formula definition: You must select a grouping context to use any report summary function
  • +
+

Resolution

+
You need to update your Report definition. See workaround here -> https://salesforce.stackexchange.com/questions/294850/grouping-error-with-prevgroupval-function
+
+
+

Invalid report type

+

Detection

+
    +
  • RegExp: Error (.*) invalid report type
  • +
+

Resolution

+
Report type is missing for report {1}
+- Open report {1} to se what report type is used
+- Retrieve the report type from an org and add it to the sfdx sources
+
+
+

Invalid scope:Mine, not allowed

+

Detection

+
    +
  • String: Invalid scope:Mine, not allowed
  • +
+

Resolution

+
Replace Mine by Everything in the list view SFDX source XML.
+Have a look at this command to manage that automatically :)
+https://sfdx-hardis.cloudity.com/hardis/org/fix/listviewmine/ 
+
+
+ +

Detection

+
    +
  • RegExp: Error (.*) Invalid field:(.*) in related list:(.*)
  • +
+

Resolution

+
Field {2} is unknown. You can:
+- Activate the related feature license or option to make {2} existing in target org
+- Update XML of {1} to remove reference to field {2} in the related list {3}
+- Update XML of {1} to remove the whole related list {3}
+Example of XML to remove:
+<relatedLists>
+  <fields>SOLUTION.ISSUE</fields>
+  <fields>SOLUTION.SOLUTION_NUMBER</fields>
+  <fields>SOLUTION.STATUS</fields>
+  <fields>CORE.USERS.ALIAS</fields>
+  <relatedList>RelatedSolutionList</relatedList>
+</relatedLists>
+
+
+

Invalid field for upsert

+

Detection

+
    +
  • RegExp: Error (.*) Invalid field for upsert, must be an External Id custom or standard indexed field: (.*) \((.*)\)
  • +
+

Resolution

+
You tried to use field {2} for an upsert call in {1}.
+- Is it declared as externalId ?
+- Is the customIndex source file present in the deployment ?
+- If it is declared as externalId and customIndex is present, you may have to go manually define the field as externalId in the target org
+
+
+

Invalid type

+

Detection

+
    +
  • RegExp: Error (.*) Invalid type: (.*) \((.*)\)
  • +
+

Resolution

+
Apex error in {1} with unknown type {2} at position {3}. If {2} is a class name, try to fix it, or maybe it is missing in the files or in package.xml !
+
+
+

Campaign can not be updated

+

Detection

+
    +
  • String: The object "Campaign" can't be updated
  • +
+

Resolution

+
Add "MarketingUser" in project-scratch-def.json features
+If it is already done, you may manually check "MarketingUser" field on the scratch org user
+
+
+

Missing field MiddleName

+

Detection

+
    +
  • String: field MiddleName
  • +
  • String: Variable does not exist: MiddleName
  • +
+

Resolution

+
MiddleNames must be activated in the target org.
+- Help: https://help.salesforce.com/articleView?id=000332623&type=1&mode=1
+- Scratch org setting:
+"nameSettings": {
+  "enableMiddleName": true
+}
+
+
+

Missing field Suffix

+

Detection

+
    +
  • String: field Suffix
  • +
+

Resolution

+
Suffix must be activated in the target org.
+- Help: https://help.salesforce.com/articleView?id=000332623&type=1&mode=1
+- Scratch org setting:
+"nameSettings": {
+  "enableNameSuffix": true
+},
+
+
+

Missing field SyncedQuoteId

+

Detection

+
    +
  • String: field SyncedQuoteId
  • +
  • String: Error force-app/main/default/objects/Quote/Quote.object-meta.xml
  • +
  • String: Error force-app/main/default/objects/Opportunity/fields/SyncedQuoteId.field-meta.xml
  • +
+

Resolution

+
Quotes must be activated in the target org.
+- Help: https://help.salesforce.com/articleView?id=sf.quotes_enable.htm&type=5
+- Scratch org setting:
+"quoteSettings": {
+  "enableQuote": true
+}
+
+
+

Missing feature ContactToMultipleAccounts

+

Detection

+
    +
  • String: no CustomObject named AccountContactRelation found
  • +
  • String: Invalid field:ACCOUNT.NAME in related list:RelatedContactAccountRelationList
  • +
+

Resolution

+
Contacts to multiple accounts be activated in the target org.
+- Help: https://help.salesforce.com/articleView?id=sf.shared_contacts_set_up.htm&type=5
+- Scratch org setting:
+"features": ["ContactsToMultipleAccounts"]
+
+
+

Missing feature Chatter Collaboration Group

+

Detection

+
    +
  • String: CollaborationGroup
  • +
+

Resolution

+
Quotes must be activated in the target org.
+- Org: Setup -> Chatter settings -> Allow Records in Groups
+- Scratch org setting:
+"chatterSettings": {
+  "allowRecordsInChatterGroup": true
+},
+
+
+

Missing feature Enhanced notes

+

Detection

+
    +
  • String: FeedItem.ContentNote
  • +
+

Resolution

+
Enhanced Notes must be activated in the target org.
+- Org: Setup -> Notes settings -> Enable Notes
+- Scratch org setting:
+"enhancedNotesSettings": {
+  "enableEnhancedNotes": true
+},
+
+
+

Missing feature Ideas notes

+

Detection

+
    +
  • String: Idea.InternalIdeasIdeaRecordType
  • +
+

Resolution

+
Ideas must be activated in the target org.
+- Org: https://help.salesforce.com/articleView?id=networks_enable_ideas.htm&type=0
+- Scratch org setting:
+"ideasSettings": {
+  "enableIdeas": true
+}
+
+
+

Missing feature Live Agent

+

Detection

+
    +
  • String: FeedItem.ContentNote
  • +
+

Resolution

+
Live Agent must be activated in the target org.
+- Org: Setup -> Live Agent Settings -> Enable Live Agent
+- Scratch org feature: LiveAgent
+
+
+

Missing feature Product Request

+

Detection

+
    +
  • String: ProductRequest
  • +
+

Resolution

+
ProductRequest object is not available in the target org.
+Maybe you would like to clean its references within Profiles / PS using the following command ?
+sf hardis:project:clean:references , then select "ProductRequest references"
+
+
+

Missing feature Social Customer Service

+

Detection

+
    +
  • String: SocialPersona.AreWeFollowing
  • +
+

Resolution

+
Social Custom Service must be activated in the target org.
+- Org: Setup -> https://help.salesforce.com/articleView?id=sf.social_customer_service_setup_enable.htm&type=5
+- Scratch org feature: SocialCustomerService
+
+
+

Missing feature Translation Workbench

+

Detection

+
    +
  • RegExp: report-meta.xml(.*)filterlanguage
  • +
+

Resolution

+
Translation workbench must be activated in the target org.
+- Org: Setup -> https://help.salesforce.com/articleView?id=sf.customize_wbench.htm&type=5
+- Scratch org:
+"languageSettings": {
+  "enableTranslationWorkbench":  true,
+  "enableEndUserLanguages": true
+}
+
+
+

Missing feature Opportunity Teams

+

Detection

+
    +
  • String: OpportunityTeam
  • +
+

Resolution

+
Opportunity Teams must be activated in the target org.
+- Org: Setup -> Opportunity Team Settings -> Enable Team Selling
+- Scratch org:
+"opportunitySettings": {
+  "enableOpportunityTeam": true
+}
+
+
+

Missing Feature Work.Com

+

Detection

+
    +
  • String: WorkBadgeDefinition
  • +
+

Resolution

+
Work.com feature must be activated in the target org.
+- Org & Scratch: https://developer.salesforce.com/docs/atlas.en-us.workdotcom_dev_guide.meta/workdotcom_dev_guide/wdc_cc_setup_dev_org.htm
+
+
+

Missing multi-currency field

+

Detection

+
    +
  • RegExp: A reference to a custom field (.*)CurrencyIsoCode
  • +
+

Resolution

+
You probably need to activate MultiCurrency (from Setup -> Company information)
+
+
+

Missing object referenced in package.xml

+

Detection

+
    +
  • RegExp: An object (.*) of type (.*) was named in package.xml, but was not found in zipped directory
  • +
+

Resolution

+
You can either:
+- Update the package.xml to remove the reference to the missing {2} {1}
+- Add the missing {2} {1} in your project source files
+
+
+

Missing Quick Action

+

Detection

+
    +
  • RegExp: Error (.*) In field: QuickAction - no QuickAction named (.*) found
  • +
+

Resolution

+
QuickAction {2} referred in {1} is unknown. You can either:
+- Make sure your QuickAction {2} is present in source files and in package.xml
+- If {2} is a standard QuickAction, activate related feature in target org
+- Solve other errors that could impact QuickAction {2}
+- Remove QuickAction {2} in the source XML of {1}. Example of XML to remove below:
+<quickActionListItems>
+  <quickActionName>FeedItem.RypplePost</quickActionName>
+</quickActionListItems>
+
+
+

Missing report

+

Detection

+
    +
  • RegExp: Error (.*) The (.*) report chart has a problem with the "reportName" field
  • +
+

Resolution

+
{1} is referring to unknown report {2}. To retrieve it, you can run:
+- sf project retrieve start -m Report:{2} -o YOUR_ORG_USERNAME
+- If it fails, looks for the report folder and add it before report name to the retrieve command (ex: MYFOLDER/MYREPORTNAME)
+
+
+

Missing Sales Team

+

Detection

+
    +
  • String: related list:RelatedAccountSalesTeam
  • +
+

Resolution

+
Account Teams must be activated in the target org.
+- Org: Setup -> Account Teams -> Enable
+- Scratch org setting:
+"accountSettings": {
+  "enableAccountTeams": true
+}
+}
+
+
+

sharing operation already in progress

+

Detection

+
    +
  • String: sharing operation already in progress
  • +
+

Resolution

+
You can not deploy multiple SharingRules at the same time. You can either:
+- Remove SharingOwnerRules and SharingRule from package.xml (so it becomes a manual operation)
+- Use sf hardis:work:save to generate a deploymentPlan in .sfdx-hardis.json,
+- If you are trying to create a scratch org, add DeferSharingCalc in features in project-scratch-def.json
+
+
+

Network issue

+

Detection

+
    +
  • String: ECONNABORTED
  • +
  • String: ECONNRESET
  • +
+

Resolution

+
The network connection has been aborted, this is a purely technical issue.
+Try again, and if you still see errors, check the status of Salesforce instance on https://status.salesforce.com
+
+
+

Not available for deploy for this organization

+

Detection

+
    +
  • RegExp: Error (.*) Not available for deploy for this organization
  • +
+

Resolution

+
The user you use for deployments probably lacks of the rights (Profiles, Permission sets...) to manage {1}.
+- Assign the deployment user to the good Permission Sets, or modify its profile rights, then try again
+
+
+

Not valid sharing model

+

Detection

+
    +
  • RegExp: Error (.*) (.*) is not a valid sharing model for (.*) when (.*) sharing model is (.*)
  • +
+

Resolution

+
It seems that Sharing Models of {1} and {4} are not compatible in target org.
+- Use compatible sharing models between {1} and {4} by updating Sharing model of {1} or {4}
+- Make sure that sfdx sources {1}.object-meta.xml and {4}.object-meta.xml and in the files, and that {1} and {4} are in package.xml in CustomObject block
+- You may directly update sharingModel in XML. For example, replace <sharingModel>ReadWrite</sharingModel> by <sharingModel>Private</sharingModel> in {3}.object-meta.xml
+
+
+

Picklist sharing is not supported

+

Detection

+
    +
  • String: Picklist sharing is not supported
  • +
+

Resolution

+
You probably changed the type of a field.
+Go manually make the change in the target org, so the deployment will pass
+
+
+

Picklist value not found

+

Detection

+
    +
  • RegExp: Picklist value: (.*) in picklist: (.*) not found
  • +
+

Resolution

+
Sources have references to value {1} of picklist {2}
+- If picklist {2} is standard, add the picklist to sfdx sources by using "sf project retrieve start -m StandardValueSet:{2}", then save again
+- Else, perform a search in all code of {1}, then remove XML tags referring to {1} (for example in record types metadatas)
+
+
+

Please choose a different name

+

Detection

+
    +
  • RegExp: Error (.*) This (.*) already exists or has been previously used(.*)Please choose a different name.
  • +
+

Resolution

+
- Rename {1} in the target org, then try again the deployment. if it succeeds, delete the renamed item.
+- or Delete {1} in the target org, then try again the deployment
+
+
+

Missing profile default application

+

Detection

+
    +
  • String: You can't remove the only default app from the profile.
  • +
+

Resolution

+
You must have a default application for a profile. You can:
+ - Update it in UI
+ - Update the XML of the profile to set "true" in the <default> tag of one of the applicationVisibilities item.
+ Ex:
+ <applicationVisibilities>
+    <application>standard__LightningSales</application>
+    <default>true</default>
+    <visible>true</visible>
+</applicationVisibilities>
+
+
+

CRM Analytics: A Recipe must specify a DataFlow

+

Detection

+
    +
  • RegExp: Error (.*) A Recipe must specify a Dataflow
  • +
+

Resolution

+
You must include related WaveDataFlow {1} in sources (and probably in package.xml too).
+To retrieve it, run: sf project retrieve start -m WaveDataFlow:{1} -u SOURCE_ORG_USERNAME
+You can also retrieve all analytics sources in one shot using sf hardis:org:retrieve:source:analytics -u SOURCE_ORG_USERNAME
+  - https://salesforce.stackexchange.com/a/365453/33522
+  - https://help.salesforce.com/s/articleView?id=000319274&type=1
+
+
+

Record Type not found

+

Detection

+
    +
  • RegExp: Error (.*) In field: recordType - no RecordType named (.*) found
  • +
+

Resolution

+
An unknown record type {2} is referenced in {1}
+- If record type {2} is not supposed to exist, perform a search in all files of {1}, then remove matching XML elements referring to this record type
+- If record type {2} is supposed to exist, you may have to create it manually in the target org to make the deployment pass
+
+
+

Objects rights on a role is below org default

+

Detection

+
    +
  • String: access level below organization default
  • +
+

Resolution

+
Your org wide settings default must be lower than the level defined in roles:
+- If you are in a scratch org, it can be fixable using "objectProperties" in project-scratch-def.json (see "Set Object-Level Sharing Settings" paragraph in page https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_scratch_orgs_def_file.htm)
+- If you are in a sandbox/dev/prod org, you need to update default org wide settings before deployment. See https://www.sfdcpoint.com/salesforce/organization-wide-defaults-owd-in-salesforce/
+
+
+

Unsupported sharing configuration

+

Detection

+
    +
  • RegExp: not supported for (.*) since it's org wide default is
  • +
+

Resolution

+
Consistency error between {1} sharing settings and {1} object configuration
+Please check https://salesforce.stackexchange.com/questions/260923/sfdx-deploying-contact-sharing-rules-on-a-fresh-deployment
+If you already did that, please try again to run the job
+
+
+

A sharing rule may be useless

+

Detection

+
    +
  • String: Required field is missing: sharingCriteriaRules
  • +
+

Resolution

+
Are you sure you need this sharing rule ? You may remove it from the sfdx project
+
+
+

Sharing recalculation lock

+

Detection

+
    +
  • String: because it interferes with another operation already in progress
  • +
  • String: Le calcul de partage demandé ne peut être traité maintenant car il interfère avec une autre opération en cours
  • +
+

Resolution

+
If you changed a field from MasterDetail to Lookup, you must do it manually in the target org before being able to deploy
+
+
+

Send email is disabled

+

Detection

+
    +
  • String: Send Email is disabled or activities are not allowed
  • +
  • String: Unknown user permission: SendExternalEmailAvailable
  • +
+

Resolution

+
Go to Email -> Deliverability -> Select value "All emails"
+
+
+

Sort order must be in sequential order

+

Detection

+
    +
  • RegExp: Error (.*) SortOrder must be in sequential order from
  • +
+

Resolution

+
You probably have a default DuplicateRule in the target org. Retrieve it from target org, or delete it manually in target org, so you can deploy.
+Ref: https://developer.salesforce.com/forums/?id=9060G000000I6SoQAK
+
+
+

Async exception in test class

+

Detection

+
    +
  • RegExp: System.AsyncException: (.*) Apex
  • +
+

Resolution

+
This may be a test class implementation issue in {1}.
+Please check https://developer.salesforce.com/forums/?id=9060G0000005kVLQAY
+
+
+

Test classes with 0% coverage

+

Detection

+
    +
  • RegExp: 0%
  • +
+

Resolution

+
Please make sure that none of the test classes are 0% covered
+
+
+

Can not test item deployment in simulation mode

+

Detection

+
    +
  • RegExp: Test only deployment cannot update
  • +
+

Resolution

+
THIS IS A FALSE POSITIVE
+When effective deployment will happen, it should pass
+
+
+

Unknown user permission: CreateAuditFields

+

Detection

+
    +
  • String: Unknown user permission: CreateAuditFields
  • +
+

Resolution

+
You need to enable the "Create audit field" permission in the target org
+Please check https://help.salesforce.com/articleView?id=000334139&type=1&mode=1
+
+
+

Unknown user permission: FieldServiceAccess

+

Detection

+
    +
  • String: Unknown user permission: FieldServiceAccess
  • +
+

Resolution

+
You need to enable the "Field Service Access" permission in the target org
+Please check https://help.salesforce.com/articleView?id=sf.fs_enable.htm&type=5
+
+
+

Unknown user permission

+

Detection

+
    +
  • String: Unknown user permission:
  • +
+

Resolution

+
You can:
+- enable the related permission in the target org
+- or remove references to the permission in source XML files (Probably a Profile or a Permission set)
+
+
+

Variable does not exist

+

Detection

+
    +
  • RegExp: Error (.*) Variable does not exist: (.*) \((.*)\)
  • +
+

Resolution

+
Apex error in {1} with unknown variable {2} at position {3}. If {2} is a class name, try to fix it, or maybe it is missing in the files or in package.xml !
+
+
+

Visibility is not allowed for type

+

Detection

+
    +
  • RegExp: Error (.*) set the visibility for a (.*) to Protected unless you are in a developer
  • +
+

Resolution

+
Update the visibility of {1} to "Public"
+
+
+

Tableau CRM / Wave digest error

+

Detection

+
    +
  • String: Fix the sfdcDigest node errors and then upload the file again
  • +
+

Resolution

+
Go to the target org, open profile "Analytics Cloud Integration User" and add READ rights to the missing object fields 
+
+
+

XML item appears more than once

+

Detection

+
    +
  • RegExp: Error (.*) Field:(.*), value:(.*) appears more than once
  • +
+

Resolution

+
You probably made an error while merging conflicts
+Look for {3} in the XML of {1}
+If you see two {2} XML blocks with {3}, please decide which one you keep and remove the other one
+
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-deployment-assistant-home/index.html b/salesforce-deployment-assistant-home/index.html new file mode 100644 index 000000000..ac5df139d --- /dev/null +++ b/salesforce-deployment-assistant-home/index.html @@ -0,0 +1,7777 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sfdx-hardis deployment assistant - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + +

sfdx-hardis Deployment Assistant

+

Salesforce DevOps AI Integration

+

Deployment errors are common and quite boring, right ?

+

Sfdx-hardis deployment assistant will help you to solve them, even if you are not using sfdx-hardis CI/CD pipelines !

+

The assistant contain core rules and can optionally be integrated with AI to provide you the best guidance :)

+

+

Flow Visual Git Diff

+

In addition to deployment tips, comments will be posted on PRs with Visual Git Diff for Flows, that will:

+
    +
  • Visually show you the differences on a diagram
  • +
  • Display the update details without having to open any XML !
  • +
+

🟩 = added

+

🟥 = removed

+

🟧 = updated

+

+

+

Integrations

+

Deployment assistant will provide tips in Pull Request comments (GitHub, Gitlab, Azure, Bitbucket).

+

It will also provide tips in console log.

+

+

Setup

+

Just follow the instructions to be ready in a few minutes

+ + + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-deployment-assistant-setup/index.html b/salesforce-deployment-assistant-setup/index.html new file mode 100644 index 000000000..1da1e4ca7 --- /dev/null +++ b/salesforce-deployment-assistant-setup/index.html @@ -0,0 +1,7863 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sfdx-hardis deployment assistant setup - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+ +
+
+ + + +
+
+ + + + + + + + + +

Setup Salesforce Deployment Assistant

+

Configure integrations

+

Make sure to have configured your GitHub, Gitlab, Azure Pipelines or BitBucket integration so the deployment assistant can post its help in Pull Request comments.

+

If you want to supercharge Salesforce deployment assistant with AI, process sfdx-hardis AI setup.

+

You can also receive Slack, Ms Teams and Email notifications in case of successful deployment.

+

If you configure JIRA or Generic Ticketing integrations, ticket numbers will be extracted and displayed in the Pull Request comment.

+

Using sfdx-hardis CI/CD

+

If you are using sfdx-hardis CI/CD, you are already all set !

+

Using custom CI/CD pipeline

+

Replace your calls to Salesforce CLI by calls to sfdx-hardis commands wrapper.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
sfdx commandCorresponding sfdx-hardis wrapper command
sf project deploy startsf hardis:project:deploy:start
sf project deploy validatesf hardis:project:deploy:validate
sf project deploy quicksf hardis:project:deploy:quick
sfdx force:source:deploy (removed on 6 november)sf hardis:source:deploy
sfdx force:source:push (removed on 6 november)sf hardis:source:push
sfdx force:mdapi:deploy (removed on 6 november)sf hardis:mdapi:deploy
+

Configure your GitHub, Gitlab, Azure Pipelines or BitBucket integration so the deployment assistant can post its help in Pull Request comments.

+

Notes:

+
    +
  • sfdx-hardis deployment assistant now works better with --json option please use it :)
  • +
+

Example

+

Replace:

+

sf project:deploy:start -x manifest/package.xml --checkonly

+

with:

+

sf hardis:project:deploy:start -x manifest/package.xml --checkonly

+

Advanced example

+

Replace:

+

sf project deploy start --dry-run --source-dir force-app --ignore-warnings --ignore-conflicts --test-level RunLocalTests --coverage-formatters json-summary --verbose --wait 120 --json

+

with:

+

sf hardis project deploy start --dry-run --source-dir force-app --ignore-warnings --ignore-conflicts --test-level RunLocalTests --coverage-formatters json-summary --verbose --wait 120 --json

+

Not updating custom CI/CD pipeline

+

You don't want to update your calls to sf project deploy start ?

+

That's ok, you can't benefit from the error management, but you can benefit from the Flows Visual Git Diff and other integrations anyway !

+

Add the Notify command to your custom CI/CD pipeline !

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-apex-tests/index.html b/salesforce-monitoring-apex-tests/index.html new file mode 100644 index 000000000..b76df4fba --- /dev/null +++ b/salesforce-monitoring-apex-tests/index.html @@ -0,0 +1,7750 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Apex tests (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Apex tests

+ + + +

Apex tests

+

Runs all local test classes of the org and calculate coverage.

+

Sfdx-hardis command: sf hardis:org:test:apex

+

Grafana example

+

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-config-azure/index.html b/salesforce-monitoring-config-azure/index.html new file mode 100644 index 000000000..c93a4e663 --- /dev/null +++ b/salesforce-monitoring-config-azure/index.html @@ -0,0 +1,7941 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Salesforce Org Monitoring with Azure - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Azure

+ + + + +

Pre-requisites

+

Configure a ByPass in Azure Settings

+
    +
  • Go to Project Settings –> Repositories –> select your repository and then click on the Security tab.
  • +
+
    +
  • Select your Build Service and set Bypass policies when pushing and Contribute to Allowed
  • +
+

+

Run sfdx-hardis configuration command

+
    +
  • Run command Configuration -> Configure Org Monitoring in VsCode SFDX Hardis, then follow instructions.
  • +
+
    +
  • When prompted to setup CI/CD variables, copy-paste their names and values in a notepad the continue the instructions
  • +
+

Create Pipeline

+

Skip this step if you already created the pipeline for the monitoring of another org

+
    +
  • Go to Project -> Pipelines (you must have Azure authorizations to access this menu)
  • +
+
    +
  • Click on New pipeline
  • +
+
    +
  • Where is your code -> Azure Repos Git
  • +
+
    +
  • Select your monitoring git repository: Existing Azure Pipelines YAML file
  • +
+
    +
  • Select your git branch then select azure-pipelines.yml
  • +
+
    +
  • Click on Continue
  • +
+
    +
  • Click on Save (contextual to the Run button)
  • +
+

+

Configure CI/CD Variables

+

For each variable sfdx-hardis command Configure org monitoring told you to define, perform the following operations

+

Create variable in Azure

+
    +
  • Go to Project -> Pipelines
  • +
  • Select your pipeline
  • +
  • Click on Edit , then on Variables
  • +
  • Input variable name and value
  • +
  • Don't forget to click on save !
  • +
+

+

Update azure-pipelines.yml

+
    +
  • Open azure-pipelines.yml in VsCode and update all places where MANUAL is found
      +
    • schedule triggers
    • +
    • environment variables
    • +
    +
  • +
+

Examples:

+
schedules:
+- cron: "0 4 * * *" # Cron format -> https://crontab.cronhub.io/
+  always: "true"
+  branches:
+    # MANUAL: Add your monitored branches here
+    include:
+    - monitoring_myclient__integ_sandbox # Name of your branch created by monitoring configuration command
+
+
    env:
+      # MANUAL: Add your branch related variables here
+      SFDX_CLIENT_ID_MONITORING_MYCLIENT__INTEG_SANDBOX: $(SFDX_CLIENT_ID_MONITORING_MYCLIENT__INTEG_SANDBOX)
+      SFDX_CLIENT_KEY_MONITORING_MYCLIENT__INTEG_SANDBOX: $(SFDX_CLIENT_KEY_MONITORING_MYCLIENT__INTEG_SANDBOX)
+      CI_COMMIT_REF_NAME: $(BRANCH_NAME)
+      CONFIG_BRANCH: $(BRANCH_NAME)
+      ORG_ALIAS: $(BRANCH_NAME)
+      CI: "true"
+
+
    +
  • Commit and push
  • +
+

Schedule the monitoring job

+

Schedule is already included within azure-pipelines.yml.

+

Default is everyday at 4 AM, but you can update the CRON expression.

+
schedules:
+- cron: "0 4 * * *" # Cron format -> https://crontab.cronhub.io/
+
+

When updated, commit and push.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-config-bitbucket/index.html b/salesforce-monitoring-config-bitbucket/index.html new file mode 100644 index 000000000..275df2a28 --- /dev/null +++ b/salesforce-monitoring-config-bitbucket/index.html @@ -0,0 +1,7790 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Salesforce Org Monitoring with Bitbucket - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Bitbucket

+ + + +

Cloning repo from VsCode

+

If you have issues to authenticate to Bitbucket from VsCode, create an App Password in Bitbucket personal settings.

+

Pre-requisites

+

There are no pre-requisites

+

Run sfdx-hardis configuration command

+
    +
  • Run command Configuration -> Configure Org Monitoring in VsCode SFDX Hardis, then follow instructions.
  • +
+

Define sfdx-hardis environment variables

+
    +
  • Go to Project -> Repository Settings > Repository Variables (you must have Bitbucket authorizations to access this menu)
  • +
  • For each variable sfdx-hardis command Configure org monitoring tells you to define, create with name and value given in sfdx-hardis command logs
  • +
+

+

Schedule the monitoring job

+
    +
  • Go to Project -> Pipelines -> Schedules
  • +
  • Click on New schedule
  • +
  • Select the target branch corresponding to the org you want to monitor
  • +
  • Select default pipeline
  • +
  • Select Schedule Daily and a time slot when no one works (for example 01:00 - 02:00)
  • +
  • Validate by clicking on Create
  • +
+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-config-github/index.html b/salesforce-monitoring-config-github/index.html new file mode 100644 index 000000000..783f54d7a --- /dev/null +++ b/salesforce-monitoring-config-github/index.html @@ -0,0 +1,7820 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Salesforce Org Monitoring with Github - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

GitHub

+ + + + +

Pre-requisites

+

None

+

Run sfdx-hardis configuration command

+
    +
  • Run command Configuration -> Configure Org Monitoring in VsCode SFDX Hardis, then follow instructions.
  • +
+

Define sfdx-hardis environment variables

+
    +
  • Go to Repository -> Settings > Secret and variables -> Actions (you must have Github authorizations to access this menu)
  • +
  • For each variable sfdx-hardis command Configure org monitoring tells you to define, click on New repository secret, with name and value given in sfdx-hardis command logs
  • +
+

+

+

Update org-monitoring.yml

+

WARNING: Scheduling can be run only on main branch on GitHub Actions, so there is a specific config.

+
    +
  • Configure all your monitored org using VsCode SFDX Hardis command "Configure Org Monitoring" (jobs will fail but that's ok)
      +
    • Reply questions, configure variables, let sfdx-hardis upload connected apps...
    • +
    • This will create one git branch per monitored org
    • +
    +
  • +
+

AND ONLY THEN:

+
    +
  • Checkout your "main" branch, create a file .github/workflows/org-monitoring.yml and copy there the content of org-monitoring.yml
      +
    • Do a CTRL+F and look for MANUAL
    • +
    • Add your monitored git branches here where asked to replace
    • +
    • Add your authentication variable names where asked to replace
    • +
    • Commit & push: there should be a SINGLE GitHub Actions job (using matrix) that will run the monitoring on all orgs
    • +
    +
  • +
+

Examples:

+
      env:
+        # MANUAL: Update variables below !
+        SFDX_CLIENT_ID_MONITORING_MY_CLIENT__INTEG_SANDBOX: ${{ secrets.SFDX_CLIENT_ID_MONITORING_MY_CLIENT__INTEG_SANDBOX}}
+        SFDX_CLIENT_KEY_MONITORING_MY_CLIENT__INTEG_SANDBOX: ${{ secrets.SFDX_CLIENT_KEY_MONITORING_MY_CLIENT__INTEG_SANDBOX}}
+        SFDX_DEPLOY_WAIT_MINUTES: 120 # Override if necessary
+
+

Schedule the monitoring job

+

Schedule is already included within org-monitoring.yml in main branch.

+

Default is everyday at midnight, but you can update the CRON expression.

+
on:
+  push:
+  # Automatically run every day at midnight
+  schedule:
+    - cron: "0 0 * * *" # Cron format -> https://crontab.cronhub.io/
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-config-gitlab/index.html b/salesforce-monitoring-config-gitlab/index.html new file mode 100644 index 000000000..91dca9bdd --- /dev/null +++ b/salesforce-monitoring-config-gitlab/index.html @@ -0,0 +1,7855 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Configure Salesforce Org Monitoring with Gitlab - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Gitlab

+ + + + +

Pre-requisites

+

Create access token

+
    +
  • Go to Project -> Settings > Access Token (you must have Gitlab authorizations to access this menu)
  • +
  • Create an access token with the following info:
      +
    • name: SFDX HARDIS MONITORING
    • +
    • role: Developer
    • +
    • scopes: read_repository, write_repository
    • +
    +
  • +
  • Copy the value of the generated token in your clipboard ! (CTRL+C)
  • +
+

+

Create CI/CD variable

+
    +
  • Go to Project -> Settings > CI/CD -> Variables (you must have Gitlab authorizations to access this menu)
  • +
  • Create the variable with the following info:
      +
    • name: ACCESS_TOKEN
    • +
    • value: Paste the value that has been generated when creating the access token in the previous step
    • +
    • Select Mask variable
    • +
    • Unselect Protected variable
    • +
    +
  • +
+

+

Run sfdx-hardis configuration command

+
    +
  • Run command Configuration -> Configure Org Monitoring in VsCode SFDX Hardis, then follow instructions.
  • +
+

Define sfdx-hardis environment variables

+
    +
  • Go to Project -> Settings > CI/CD -> Variables (you must have Gitlab authorizations to access this menu)
  • +
  • For each variable sfdx-hardis command Configure org monitoring tells you to define, create with name and value given in sfdx-hardis command logs
  • +
+

+

Schedule the monitoring job

+
    +
  • Go to Project -> Build -> Pipeline schedules
  • +
  • Click on New schedule
  • +
  • Input custom interval pattern as CRON expression, for example:
      +
    • 0 1 * * * will run the monitoring job every day at 1 AM
    • +
    • 0 22 * * * will run the monitoring job everyday at 10 PM
    • +
    +
  • +
  • Select the CRON TimeZone (for example [UTC+2] Paris)
  • +
  • Select the target branch corresponding to the org you want to monitor
  • +
  • Validate by clicking on Create Pipeline Schedule
  • +
+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-config-home/index.html b/salesforce-monitoring-config-home/index.html new file mode 100644 index 000000000..0f1a93b2d --- /dev/null +++ b/salesforce-monitoring-config-home/index.html @@ -0,0 +1,7970 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + How to monitor your Salesforce Org - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Configuration guide

+ + + + +

Video tutorial

+
+ +

Instructions

+

Common instructions

+

All you need to configure sfdx-hardis Org Monitoring is a GitHub , Gitlab, Azure or BitBucket repository.

+
    +
  • Create and clone a git repository (initialize it with README)
  • +
  • Open it with Visual Studio Code, then open VsCode SFDX Hardis extension menu. +
  • +
+
    +
  • Follow instructions, that can be specific according to your git provider
  • +
+
+

Tip: Schedule monitoring jobs at different hours so the notifications are more readable, for example production at 1AM and preprod at 2AM

+
+

Github

+ +

Gitlab

+ +

Azure

+ +

Bitbucket

+ +

Notifications

+

For a better user experience, it is highly recommended to configure notifications !

+ +

You can decide to run commands but not send some notifications by defining either a notificationsDisable property in .sfdx-hardis.yml, or a comma separated list in env variable NOTIFICATIONS_DISABLE

+

Example in .sfdx-hardis.yml:

+
notificationsDisable:
+  - METADATA_STATUS
+  - UNUSED_METADATAS
+
+

Example in env var:

+
NOTIFICATIONS_DISABLE=METADATA_STATUS,UNUSED_METADATAS
+
+

Monitoring commands

+

You can decide to disable commands by defining either a monitoringDisable property in .sfdx-hardis.yml, or a comma separated list in env variable MONITORING_DISABLE

+

Example in .sfdx-hardis.yml:

+
monitoringDisable:
+  - METADATA_STATUS
+  - UNUSED_METADATAS
+
+

Example in env var:

+
MONITORING_DISABLE=METADATA_STATUS,UNUSED_METADATAS
+
+

Troubleshooting

+

You might want to customize which metadatas types are backuped, because you can't monitor more than 10000 items.

+

If there are more than 10000 items, your monitoring job will crash.

+

In that case, you can:

+
    +
  • Single Branch scope: Manually update file manifest/package-skip-items.xml in the branch corresponding to an org, then commit and push
  • +
  • All branches scope: Define CI/CD env var MONITORING_BACKUP_SKIP_METADATA_TYPES with the list of additional metadata types you want to skip
      +
    • example: `MONITORING_BACKUP_SKIP_METADATA_TYPES=CustomLabel,StaticResource,Translation`
    • +
    +
  • +
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-deprecated-api-calls/index.html b/salesforce-monitoring-deprecated-api-calls/index.html new file mode 100644 index 000000000..e45490525 --- /dev/null +++ b/salesforce-monitoring-deprecated-api-calls/index.html @@ -0,0 +1,7750 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Suspect Setup Actions (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+ +
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-home/index.html b/salesforce-monitoring-home/index.html new file mode 100644 index 000000000..6acc6740b --- /dev/null +++ b/salesforce-monitoring-home/index.html @@ -0,0 +1,7850 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + How to monitor your Salesforce Org - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Monitoring home

+ + + + +

Monitor your Salesforce org with sfdx-hardis

+
+

This feature worked yesterday in production, but today it crashes, what happened ?

+
+

Instead of reading, watch the presentation at Dreamforce 24 conference in San Francisco !

+
+ +

or if you like reading, here are the slides !

+
+ +

Salesforce provide Audit Trail to trace configuration updates in production or sandbox orgs.

+

You can know who updated what, but not with details (before / after).

+

Sfdx-hardis monitoring provides a simple way to Backup your orgs metadatas everyday, or even several times a day, and provides an exact and detailed comparison with the previous metadata configuration (using git commits comparison)

+

Extra indicators are also available out of the box, like:

+ +

You don't need to work in CI/CD to use Monitoring, it is compliant with any API enabled org :)

+

Installation and usage are admin-friendly, and notifications can be sent via Slack or Microsoft Teams.

+

Example of visualization in Grafana

+

+

+

+

Example notifications with Slack

+

+

Example of a monitoring git repository

+

+

How does it work ?

+

Every night (or even more frequently, according to your schedule), a CI job will be triggered.

+

It will extract all the metadatas of your org, then push a new commit in the monitoring repository in case there are updates since the latest metadata backup.

+

+

Example workflow with GitHub actions

+

+

Example diff visualization with GitLens

+

+

The list of updated metadatas will be sent via notification to a Slack and/or Microsoft Teams channel.

+

After the metadata backup, other jobs will be triggered (Apex tests, Code Quality, Legacy API checks + your own commands), and their results will be stored in job artifacts and sent via notifications.

+

Are you ready ? Configure the monitoring on your orgs !

+

All Monitoring Commands

+

The following checks are active out of the box.

+

In order to avoid to overflow channels of notifications, some commands are run everyday whereas less critical ones are run weekly (on saturday).

+

You can force the daily run of all commands by defining env var MONITORING_IGNORE_FREQUENCY=true.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CheckFrequency
Metadata BackupDaily
Detect suspect setup actions in major orgDaily
Apex testsDaily
Quality Checks with MegaLinterDaily
Detect limits issuesDaily
Detect calls to deprecated API versionsDaily
Check Release UpdatesWeekly
Detect inactive usersWeekly
Detect not used Apex Classes (Batch,Schedulable,Queueable)Weekly
Detect not used Connected AppsWeekly
Detect unused licensesWeekly
Detect custom elements with no access rights defined in permission setsWeekly
Detect custom labels and custom permissions that are not in useWeekly
Detect inactive metadataWeekly
Detect missing attributesWeekly
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-inactive-metadata/index.html b/salesforce-monitoring-inactive-metadata/index.html new file mode 100644 index 000000000..d89058610 --- /dev/null +++ b/salesforce-monitoring-inactive-metadata/index.html @@ -0,0 +1,7752 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Inactive Metadatas (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Inactive metadata

+ + + +

Detect inactive metadata

+

Are you sure this inactive flow should be inactive ?

+

And what about this deactivated Validation Rule ?

+

Maybe it's time to remove them !

+

Sfdx-hardis command: sf hardis:lint:metadatastatus

+

Key: METADATA_STATUS

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-inactive-users/index.html b/salesforce-monitoring-inactive-users/index.html new file mode 100644 index 000000000..6a545d5e2 --- /dev/null +++ b/salesforce-monitoring-inactive-users/index.html @@ -0,0 +1,7750 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Inactive Users (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Inactive users

+ + + +

Detect inactive users

+

Detect if you are paying licenses for users that did not login for more than 6 months !

+

Sfdx-hardis command: sf hardis:org:diagnose:unusedusers

+

Key: UNUSED_USERS

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-metadata-backup/index.html b/salesforce-monitoring-metadata-backup/index.html new file mode 100644 index 000000000..8f44688f2 --- /dev/null +++ b/salesforce-monitoring-metadata-backup/index.html @@ -0,0 +1,7749 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Metadata backup (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Metadata Backup

+ + + +

Metadata Backup

+

Adds a new commit in the git branch with the newest updates since latest monitoring run.

+

Sfdx-hardis command: sf hardis:org:monitor:backup

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-missing-access/index.html b/salesforce-monitoring-missing-access/index.html new file mode 100644 index 000000000..09d75cfb6 --- /dev/null +++ b/salesforce-monitoring-missing-access/index.html @@ -0,0 +1,7750 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Missing metadata access (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Metadatas without access

+ + + +

Detect custom elements with no access rights defined in permission sets

+

If there are elements that nobody has access to (not existing on any Profile or Permission Set), maybe they should be removed !

+

Sfdx-hardis command: sf hardis:lint:access

+

Key: LINT_ACCESS

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-missing-metadata-attributes/index.html b/salesforce-monitoring-missing-metadata-attributes/index.html new file mode 100644 index 000000000..7590e6cd0 --- /dev/null +++ b/salesforce-monitoring-missing-metadata-attributes/index.html @@ -0,0 +1,7750 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Missing metadata attributes (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Missing metadata attributes

+ + + +

Detect missing attributes

+

Follow best practices by documenting your data model !

+

Sfdx-hardis command: sf hardis:lint:missingattributes

+

Key: MISSING_ATTRIBUTES

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-org-limits/index.html b/salesforce-monitoring-org-limits/index.html new file mode 100644 index 000000000..df3f9ccab --- /dev/null +++ b/salesforce-monitoring-org-limits/index.html @@ -0,0 +1,7764 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org limits (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Limits issues

+ + + +

Detect org limits issues

+

There are many limits on a Salesforce org:

+
    +
  • Data storage
  • +
  • File storage
  • +
  • Daily API Calls
  • +
  • Daily Bulk API Calls
  • +
  • Daily Platform events
  • +
  • and about 40 others !
  • +
+

This feature controls that they are not reached, and will send notifications:

+
    +
  • Info: > 50%
  • +
  • Warning > 75%
  • +
  • Error > 100%
  • +
+

Sfdx-hardis command: sf hardis:org:monitor:limits

+

Key: ORG_LIMITS

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-quality-checks/index.html b/salesforce-monitoring-quality-checks/index.html new file mode 100644 index 000000000..8b93125a4 --- /dev/null +++ b/salesforce-monitoring-quality-checks/index.html @@ -0,0 +1,7704 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Quality Checks with MegaLinter (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Quality Checks with MegaLinter

+ + + +

Quality Checks with MegaLinter

+

Will check if best practices are applied for:

+
    +
  • Apex with PMD
  • +
  • LWC & Aura with eslint
  • +
  • Flows with Lightning Flow Scanner
  • +
  • Security with checkov, gitleaks, secretlint, trivy...
  • +
+

Full list in MegaLinter Documentation

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-release-updates/index.html b/salesforce-monitoring-release-updates/index.html new file mode 100644 index 000000000..f6e3e5bd9 --- /dev/null +++ b/salesforce-monitoring-release-updates/index.html @@ -0,0 +1,7637 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Check Release Updates (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Check Release Updates (Salesforce monitoring)

+ + + +

Check Release Updates

+

Before publishing Breaking Changes ❌, Salesforce announce them in the setup menu Release Updates

+

⚠️ Some of them are very important, because if you don't make the related upgrades in time (ex: before Winter 25) , your production org can crash !

+

This command will extract the Release Updates that needs to be checked in your org !

+

Sfdx-hardis command: sf hardis:org:diagnose:releaseupdates

+

Key: RELEASE_UPDATES*

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-suspect-audit-trail/index.html b/salesforce-monitoring-suspect-audit-trail/index.html new file mode 100644 index 000000000..2ebf5360e --- /dev/null +++ b/salesforce-monitoring-suspect-audit-trail/index.html @@ -0,0 +1,7750 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Suspect Setup Actions (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Suspect Setup Actions

+ + + +

Detect suspect setup actions in major org

+

Will extract from audit trail all actions that are considered as suspect, excepted the ones related to the deployment user and a given list of users, like the release manager.

+

Sfdx-hardis command: sf hardis:org:diagnose:audittrail

+

Key: AUDIT_TRAIL

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-unused-apex-classes/index.html b/salesforce-monitoring-unused-apex-classes/index.html new file mode 100644 index 000000000..05a2cea10 --- /dev/null +++ b/salesforce-monitoring-unused-apex-classes/index.html @@ -0,0 +1,7752 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Detect unused Apex Classes (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Unused Apex Classes

+ + + +

Detect unused Apex Classes

+

List all async Apex classes (Batch,Queueable,Schedulable) that has not been called for more than 365 days.

+

The result class list probably can be removed from the project, and that will improve your test classes performances :)

+

The command uses queries on AsyncApexJob and CronTrigger technical tables to build the result.

+

Sfdx-hardis command: sf hardis:org:diagnose:unused-apex-classes

+

Key: UNUSED_APEX_CLASSES

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-unused-connected-apps/index.html b/salesforce-monitoring-unused-connected-apps/index.html new file mode 100644 index 000000000..897bf056d --- /dev/null +++ b/salesforce-monitoring-unused-connected-apps/index.html @@ -0,0 +1,7754 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Detect unused Connected Apps (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Unused Connected Apps

+ + + +

Detect unused Connected Apps

+

List all Connected Apps that might be not used anymore

+

You might disable them or even delete them to clean your org from technical debt and avoid security risks.

+

Sfdx-hardis command: sf hardis:org:diagnose:unused-connected-apps

+

Key: CONNECTED_APPS

+

Grafana example

+

TODO

+ + +

Slack example

+

TODO

+ + + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-unused-licenses/index.html b/salesforce-monitoring-unused-licenses/index.html new file mode 100644 index 000000000..31baf0c7e --- /dev/null +++ b/salesforce-monitoring-unused-licenses/index.html @@ -0,0 +1,7754 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unused Licenses (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Unused licenses

+ + + +

Detect unused licenses

+

When you assign a Permission Set to a user, and that this Permission Set is related to a Permission Set License, a Permission Set License Assignment is automatically created for the user.

+

But when you unassign this Permission Set from the user, the Permission Set License Assignment is not deleted.

+

This leads that you can be charged for Permission Set Licenses that are not used !

+

This command detects such useless Permission Set Licenses Assignments and suggests to delete them.

+

Many thanks to Vincent Finet for the inspiration during his great speaker session at French Touch Dreamin '23, and his kind agreement for reusing such inspiration in this command :)

+

Sfdx-hardis command: sf hardis:org:diagnose:unusedlicenses

+

Key: UNUSED_LICENSES

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-monitoring-unused-metadata/index.html b/salesforce-monitoring-unused-metadata/index.html new file mode 100644 index 000000000..44bb7baa1 --- /dev/null +++ b/salesforce-monitoring-unused-metadata/index.html @@ -0,0 +1,7743 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unused Metadatas (Salesforce monitoring) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Unused Custom Labels

+ + + +

Detect metadatas that are not used

+

If there are elements that are not used by anything, maybe they should be removed !

+

Today working with:

+
    +
  • Custom Labels
  • +
  • Custom Permissions
  • +
+

Sfdx-hardis command: sf hardis:lint:unusedmetadatas

+

Key: UNUSED_METADATAS

+

Grafana example

+

+

Slack example

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salesforce-project-documentation/index.html b/salesforce-project-documentation/index.html new file mode 100644 index 000000000..95da1cec5 --- /dev/null +++ b/salesforce-project-documentation/index.html @@ -0,0 +1,7837 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Generate Salesforce Project Documentation - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Project & Flows Documentation

+ + + +

Salesforce Project Documentation

+

With a single command, you can generate a Web Site documenting your Salesforce metadatas (like Flows)

+

+

How To generate

+ + +

Run Locally

+
    +
  • Run command Documentation Generation > Run local HTML Doc Pages (Note: you need Python on your computer)
      +
    • Corresponding command lines: pip install mkdocs-material mdx_truly_sane_lists, then mkdocs serve
    • +
    +
  • +
+ +

Host on Salesforce org

+

You can also host the HTML documentation directly in your Salesforce org !

+

+

Manually

+ +
    +
  • Set generated Custom Tab as Default On on your Profile if necessary
  • +
+
    +
  • Assign generated Permission Set to the users you want to access the SFDX Doc tab
  • +
+
    +
  • Add the tab in a Lightning Application (optional)
  • +
+

From CI/CD

+

If using sfdx-hardis monitoring, just set the variable SFDX_HARDIS_DOC_DEPLOY_TO_ORG=true (or the .sfdx-hardis.yml variable docDeployToOrg: true)

+

If using custom pipelines, add sf hardis:doc:project2markdown --with-history then sf hardis:doc:mkdocs-to-salesforce in your workflow.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/schema/schema_doc.css b/schema/schema_doc.css new file mode 100644 index 000000000..e1f3a5112 --- /dev/null +++ b/schema/schema_doc.css @@ -0,0 +1,181 @@ +body { + font: 16px/1.5em "Overpass", "Open Sans", Helvetica, sans-serif; + color: #333; + font-weight: 300; + padding: 40px; +} + +.btn.btn-link { + font-size: 18px; + user-select: text; +} + +.jsfh-animated-property { + animation: eclair; + animation-iteration-count: 1; + animation-fill-mode: forwards; + animation-duration: .75s; + +} + +@keyframes eclair { + 0%,100% { + transform: scale(1); + } + 50% { + transform: scale(1.03); + } +} + +.btn.btn-primary { + margin: 10px; +} + +.btn.example-show.collapsed:before { + content: "show" +} + +.btn.example-show:before { + content: "hide" +} + +.description.collapse:not(.show) { + max-height: 100px !important; + overflow: hidden; + + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; +} + +.description.collapsing { + min-height: 100px !important; +} + +.collapse-description-link.collapsed:after { + content: '+ Read More'; +} + +.collapse-description-link:not(.collapsed):after { + content: '- Read Less'; +} + +.badge { + font-size: 100%; + margin-bottom: 0.5rem; + margin-top: 0.5rem; +} + +.badge.value-type { + font-size: 120%; + margin-right: 5px; + margin-bottom: 10px; +} + + +.badge.default-value { + font-size: 120%; + margin-left: 5px; + margin-bottom: 10px; +} + +.badge.restriction { + display: inline-block; +} + +.badge.required-property,.badge.deprecated-property,.badge.pattern-property,.badge.no-additional { + font-size: 100%; + margin-left: 10px; +} + +.accordion div.card:only-child { + border-bottom: 1px solid rgba(0, 0, 0, 0.125); +} + +.examples { + padding: 1rem !important; +} + +.examples pre { + margin-bottom: 0; +} + +.highlight.jumbotron { + padding: 1rem !important; +} + +.generated-by-footer { + margin-top: 1em; + text-align: right; +} + +/* From https://github.com/richleland/pygments-css/blob/master/friendly.css, see https://github.com/trentm/python-markdown2/wiki/fenced-code-blocks */ +.highlight { background: #e9ecef; } /* Changed from #f0f0f0 in the original style to be the same as bootstrap's jumbotron */ +.highlight .hll { background-color: #ffffcc } +.highlight .c { color: #60a0b0; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #60a0b0; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .cpf { color: #60a0b0; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #40a070 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #40a070 } /* Literal.Number.Bin */ +.highlight .mf { color: #40a070 } /* Literal.Number.Float */ +.highlight .mh { color: #40a070 } /* Literal.Number.Hex */ +.highlight .mi { color: #40a070 } /* Literal.Number.Integer */ +.highlight .mo { color: #40a070 } /* Literal.Number.Oct */ +.highlight .sa { color: #4070a0 } /* Literal.String.Affix */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #06287e } /* Name.Function.Magic */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ +.highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */ diff --git a/schema/schema_doc.min.js b/schema/schema_doc.min.js new file mode 100644 index 000000000..17eceaf59 --- /dev/null +++ b/schema/schema_doc.min.js @@ -0,0 +1 @@ +$(document).on("click",'a[href^="#"]',function(event){event.preventDefault();history.pushState({},"",this.href)});function flashElement(elementId){myElement=document.getElementById(elementId);myElement.classList.add("jsfh-animated-property");setTimeout(function(){myElement.classList.remove("jsfh-animated-property")},1e3)}function setAnchor(anchorLinkDestination){history.pushState({},"",anchorLinkDestination)}function anchorOnLoad(){let linkTarget=decodeURIComponent(window.location.hash.split("?")[0].split("&")[0]);if(linkTarget[0]==="#"){linkTarget=linkTarget.substr(1)}if(linkTarget.length>0){anchorLink(linkTarget)}}function anchorLink(linkTarget){const target=$("#"+linkTarget);target.parents().addBack().filter(".collapse:not(.show), .tab-pane, [role='tab']").each(function(index){if($(this).hasClass("collapse")){$(this).collapse("show")}else if($(this).hasClass("tab-pane")){const tabToShow=$("a[href='#"+$(this).attr("id")+"']");if(tabToShow){tabToShow.tab("show")}}else if($(this).attr("role")==="tab"){$(this).tab("show")}});setTimeout(function(){let targetElement=document.getElementById(linkTarget);if(targetElement){targetElement.scrollIntoView({block:"center",behavior:"smooth"});setTimeout(function(){flashElement(linkTarget)},500)}},1e3)} \ No newline at end of file diff --git a/schema/sfdx-hardis-json-schema-parameters.html b/schema/sfdx-hardis-json-schema-parameters.html new file mode 100644 index 000000000..2db1ff115 --- /dev/null +++ b/schema/sfdx-hardis-json-schema-parameters.html @@ -0,0 +1,5830 @@ + + + + + + + + + + + + + + + + sfdx-hardis configuration + + + +

sfdx-hardis configuration

Type: object
+

Configuration file definition for sfdx-hardis Salesforce DX plugin

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

Allowed org types

Type: array of enum (of string)
+

Types of orgs allowed for config & development. If not set, sandbox and scratch are allowed by default

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: enum (of string)
+
+

Must be one of:

+
  • "sandbox"
  • "scratch"
+
+ + + + + + +
+

+
Example:
+
[
+    "sandbox"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Auto-Cleaning types

Type: array of enum (of string)
+

When saving a sfdx-hardis task, the list of cleanings will be automatically applied to sfdx sources

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: enum (of string)
+
+

Must be one of:

+
  • "caseentitlement"
  • "checkPermissions"
  • "dashboards"
  • "datadotcom"
  • "destructivechanges"
  • "flowPositions"
  • "localfields"
  • "listViewsMine"
  • "minimizeProfiles"
  • "productrequest"
  • "sensitiveMetadatas"
  • "systemDebug"
  • "v60"
+
+ + + + + + +
+

+
Example:
+
[
+    "dashboards",
+    "datadotcom",
+    "destructivechanges"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Auto-Remove User Permissions on profiles

Type: array of string
+

When saving a sfdx-hardis task, these permissions will be removed from profiles

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+

+
Example:
+
[
+    "EnableCommunityAppLauncher",
+    "FieldServiceAccess",
+    "OmnichannelInventorySync"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Auto-Retrieve when pull

Type: array of string
+

When calling hardis:scratch:pull, if you define metadatas (named or not), they will also be retrieved using force:source:retrieve

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+

+
Examples:
+
[
+    "CustomApplication"
+]
+
+
[
+    "CustomApplication:MyApp1",
+    "CustomApplication:MyApp2"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Minimum apex test coverage %

Type: number Default: 75.0
+

Minimum percentage of apex code coverage accepted

+
+ + + + + +
+
Examples:
+
80.0
+
+
95.0
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Available projects

Type: array of string
+

List of business projects that are managed in the same repository. Will be used to build git branch name when using hardis:work:new

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+

+
Example:
+
[
+    "sales_cloud",
+    "service_cloud",
+    "community"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Available target branches

Type: array of string
+

List of git branches that can be used as target for merge requests

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+

+
Example:
+
[
+    "develop",
+    "develop_next"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

New branches prefixes choices

Type: array Default: [{"title": "Feature", "value": "feat", "description": "New feature, evolution of an existing feature... If you don't know, just select Feature"}, {"title": "Debug", "value": "fix", "description": "A bug has been identified and you are the right person to solve it !"}]
+

When calling hardis:work:new, you can override the default branch prefixes. Input title, value and description for each of them

+
+ + + + + + No Additional Items
+
Example:
+
[
+    {
+        "title": "Feature",
+        "value": "feat",
+        "description": "New feature, evolution of an existing feature... If you don't know, just select Feature"
+    },
+    {
+        "title": "Debug",
+        "value": "fix",
+        "description": "A bug has been identified and you are the right person to solve it !"
+    }
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Clean XML Patterns

Type: array of object
+

List of patterns to automatically clean XML files

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: object
+

Clean XML pattern and xpaths

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

Glob pattern

Type: string
+

Glob pattern to identify XML files to clean

+
+ + + + + +
+
Example:
+
"/**/*.flexipage-meta.xml"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

XPath list

Type: array of string
+

XPaths to identify elements to remove

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+

+
Example:
+
[
+    "//ns:flexiPageRegions//ns:name[contains(text(),'dashboardName')]"
+]
+
+
+
+
+
+
+
+

+
Example:
+
[
+    {
+        "globPattern": "/**/*.flexipage-meta.xml",
+        "xpaths": [
+            "//ns:flexiPageRegions//ns:name[contains(text(),'dashboardName')]"
+        ]
+    },
+    {
+        "globPattern": "/**/*.layout-meta.xml",
+        "xpaths": [
+            "//ns:relatedLists//ns:relatedList[contains(text(),'RelatedSolutionList')]"
+        ]
+    }
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Commands Pre-Deployment

Type: array of object
+

List of commands to run before a deployment

+
+
+

The following properties are required:

+
  • id
  • label
  • command
+
+ + + + + No Additional Items

Each item of this array must be:

+
+
+ + +

Command

Type: object
+

Command definition

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

Id

Type: string
+

Identifier of the command (can be any string)

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Label

Type: string
+

Label of the command (what does it do ?)

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Command

Type: string
+

Command line to run

+
+ + + + + + +
+
+
+
+
+

+
Example:
+
[
+    {
+        "id": "knowledgeUnassign",
+        "label": "Remove KnowledgeUser right to the user who has it",
+        "command": "sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json"
+    },
+    {
+        "id": "knowledgeAssign",
+        "label": "Assign Knowledge user to desired username",
+        "command": "sf data update record --sobject User --where \"Username='deployment-user@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json"
+    }
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Commands Post-Deployment

Type: array of object
+

List of commands to run after a deployment

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + +

Command

Type: object
+

Command definition

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

Id

Type: string
+

Identifier of the command (can be any string)

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Label

Type: string
+

Label of the command (what does it do ?)

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Command

Type: string
+

Command line to run

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Context

Type: enum (of string) Default: "all"
+

Context when the command must be run

+
+

Must be one of:

+
  • "all"
  • "check-deployment-only"
  • "process-deployment-only"
+
+ + + + + +
+
Examples:
+
"all"
+
+
"check-deployment-only"
+
+
"process-deployment-only"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Skip if error

Type: boolean Default: "false"
+

Do not run the command if there is a deployment error

+
+ + + + + + +
+
+
+
+
+

+
Example:
+
[
+    {
+        "id": "knowledgeUnassign",
+        "label": "Remove KnowledgeUser right to the user who has it",
+        "command": "sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json"
+    },
+    {
+        "id": "knowledgeAssign",
+        "label": "Assign Knowledge user to desired username",
+        "command": "sf data update record --sobject User --where \"Username='admin-user@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json"
+    }
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Custom commands

Type: array of object
+

List of custom commands for VsCode SFDX-Hardis extension

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: object
+

Custom command definition

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

Id

Type: string
+

Identifier of the menu (can be any string)

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Label

Type: string
+

Label of the menu

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Label

Type: array of object
+

List of commands of the menu

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: object
+

Custom command definition

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

Id

Type: string
+

Identifier of the command (can be any string)

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Label

Type: string
+

Label of the command that will appear in menu

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Icon

Type: string
+

Icon (can be any of svg icons of this list: https://github.com/hardisgroupcom/vscode-sfdx-hardis/tree/master/resources

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Tooltip

Type: string
+

Text that will appear when user will hover the command

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Command

Type: string
+

Command line to run when clicking on the menu

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Help url

Type: string
+

URL for help page of the command

+
+ + + + + + +
+
+
+
+
+
+
+
+
+
+
+

+
Example:
+
[
+    {
+        "id": "custom-menu",
+        "label": "Custom commands",
+        "commands": [
+            {
+                "id": "generate-manifest-xml",
+                "label": "Generate manifest",
+                "icon": "file.svg",
+                "tooltip": "Generates a manifest package.xml using local sfdx source files",
+                "command": "sf project generate manifest --source-path force-app --name myNewManifest"
+            },
+            {
+                "id": "list-all-orgs",
+                "label": "List all orgs",
+                "icon": "salesforce.svg",
+                "tooltip": "List all orgs that has already been authenticated using sfdx",
+                "command": "sf org list --all"
+            }
+        ]
+    },
+    {
+        "id": "custom-menu-2",
+        "label": "Another custom menu",
+        "commands": [
+            {
+                "id": "echo",
+                "label": "Echo something",
+                "icon": "user.svg",
+                "tooltip": "Useless commands just to show that we can use not sfdx commands too",
+                "command": "echo \"Something\""
+            }
+        ]
+    }
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Custom commands position

Type: enum (of string) Default: "first"
+

Position of custom commands in the menu (first or last)

+
+

Must be one of:

+
  • "first"
  • "last"
+
+ + + + + +
+
Examples:
+
"first"
+
+
"last"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Custom Org Colors

Type: object
+

Custom colors set by VsCode SFDX Hardis

+
+ + + + + + +
+
+
+

+ +

+
+ +
+

Additional Properties of any type are allowed.

+ + Type: object
+ + + + + + + +
+
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Custom plugins

Type: array of object
+

List of additional plugins that will be displayed in VsCode SFDX-Hardis Dependencies panel

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + +

Plugin

Type: object
+

Plugin definition

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

Name

Type: string
+

Name of the plugin npm package

+
+ + + + + +
+
Examples:
+
"mo-dx-plugin"
+
+
"shane-sfdx-plugins"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Name

Type: string
+

Url of plugin documentation

+
+ + + + + +
+
Examples:
+
"https://github.com/msrivastav13/mo-dx-plugin"
+
+
"https://github.com/mshanemc/shane-sfdx-plugins"
+
+
+
+
+
+
+
+

+
Example:
+
[
+    {
+        "name": "mo-dx-plugin",
+        "helpUrl": "https://github.com/msrivastav13/mo-dx-plugin"
+    },
+    {
+        "name": "shane-sfdx-plugins",
+        "helpUrl": "https://github.com/mshanemc/shane-sfdx-plugins"
+    }
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Data packages

Type: array of object
+

List of data packages

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: object
+

Data package

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

SFDMU Data project path

Type: string
+

Path to SFDMU project

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

SFDMU Data project path

Type: boolean
+

Path to SFDMU project

+
+ + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Defaut package installation key

Type: string
+

When generating a new package version protected with password, use this value as default package installation key

+
+ + + + + +
+
Examples:
+
"hardis"
+
+
"myPassword"
+
+
"dFGGF43656YfdFDG{{{dhgfh:::;FSEDSFd78"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Default pull/merge request target org

Type: string Default: "developpement"
+

When creating a new sfdx-hardis task, this git branch is used as base to create the feature/debug sub branch. The merge request will later have this branch as target.

+
+ + + + + +
+
Examples:
+
"developpement"
+
+
"dev_lot2"
+
+
"hotfixes"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Deployment plan

Type: object
+

Deployment plan that will be performed during deployments. Can be based on packageXmlFile for sources or on dataPath for sfdmu data deployments

+
+ + + + + +
+
Example:
+
{
+    "packages": [
+        {
+            "label": "Import EmailTemplate records",
+            "dataPath": "scripts/data/EmailTemplate",
+            "order": -21
+        },
+        {
+            "label": "Deploy EmailTemplate",
+            "packageXmlFile": "manifest/splits/packageXmlEmails.xml",
+            "order": -20
+        },
+        {
+            "label": "Deploy Flow-Workflow",
+            "packageXmlFile": "manifest/splits/packageXmlFlowWorkflow.xml",
+            "order": 6
+        }
+    ]
+}
+
+
+
+
+
+

+ +

+
+ +
+
+ +

List of packages to deploy

Type: array of object
+

During deployment, main package.xml will be split into these packages. Can also contain data packages

+
+
+

The following properties are required:

+
  • label
  • order
+
+ + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: object
+

Source or data package to deploy

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

Path to SFDMU data project to deploy

Type: string
+ + + + + + +
+
Example:
+
"scripts/data/EmailTemplate"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Source or data package label

Type: string
+ + + + + + +
+
Examples:
+
"Deploy EmailTemplate"
+
+
"Import EmailTemplate records"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Execution order in deployment plan

Type: number
+ + + + + + +
+
Examples:
+
-20
+
+
13
+
+
50
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Path to package.xml file to use for deployment

Type: string
+ + + + + + +
+
Example:
+
"manifest/splits/packageXmlEmails.xml"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Wait after install (seconds)

Type: number
+

Delay to wait before installing the next package

+
+ + + + + +
+
Examples:
+
10
+
+
20
+
+
+
+
+
+
+
+

+
Example:
+
[
+    {
+        "label": "Import EmailTemplate records",
+        "dataPath": "scripts/data/EmailTemplate",
+        "order": -21
+    },
+    {
+        "label": "Deploy EmailTemplate",
+        "packageXmlFile": "manifest/splits/packageXmlEmails.xml",
+        "order": -20
+    }
+]
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Dev Hub org alias

Type: string Default: ""
+

Dev Hub alias, usually DevHub_ProjectName

+
+ + + + + +
+
Examples:
+
"DevHub_MyClientMyProject"
+
+
"DevHub_GoogleGmail"
+
+
"DevHub_AppleIWatch"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Dev Hub Username

Type: string Default: ""
+

Dev Hub username, used to authenticate to DevHub from CI jobs

+
+ + + + + +
+
Examples:
+
"cicd-user@myclient.com"
+
+
"scratch-user@google.fr"
+
+
"scratch-user@apple.fr"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Extends remote configuration URL

Type: string
+

You can base your local sfdx-hardis configuration on a remote config file. That allows you to have the same config base for all your projects

+
+ + + + + +
+
Example:
+
"https://raw.githubusercontent.com/worldcompany/shared-config/main/.sfdx-hardis.yml"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Initial Permission Sets

Type: array
+

When creating a scratch org, Admin user will be automatically assigned to those permission sets

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: object or string
+

Permission Set or Permission Set Group

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

Name

Type: string
+

Permission Set or Permission Set Group name

+
+ + + + + +
+
Example:
+
[
+    "MyPermissionSet",
+    "MyPermissionSetGroup",
+    "MyPermissionSetGroup2"
+]
+
+
+
+
+
+
+
+

+
Example:
+
[
+    "MyPermissionSet",
+    "MyPermissionSetGroup"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Installed Packages

Type: array of object
+

Defines the list of packages installed on the project. Use

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + +

Salesforce package

Type: object
+

Salesforce package info (managed, unlocked or unmanaged)

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

(unused) PackageId

Type: string
+ + + + + + +
+
Example:
+
"0A35r000000GveVCAS"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Subscriber Package Id

Type: string
+ + + + + + +
+
Example:
+
"033b0000000Pf2AAAS"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Subscriber Package Name

Type: string
+ + + + + + +
+
Example:
+
"Files Attachment Notes"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Subscriber Package NameSpace

Type: string or null
+ + + + + + +
+
Example:
+
"fan_astrea"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Subscriber Version Id (IMPORTANT)

Type: string
+ + + + + + +
+
Example:
+
"04t0o000003nRWAAA2"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Subscriber Version Name

Type: string
+ + + + + + +
+
Example:
+
"Summer2021"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Subscriber Version Number

Type: string
+ + + + + + +
+
Example:
+
"1.22.0.2"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Install during deployments

Type: boolean Default: false
+

If true, during deployments this package will be installed in target org if not installed yet

+
+ + + + + +
+
Examples:
+
true
+
+
false
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Install on scratch orgs

Type: boolean Default: false
+

If true, this package will be installed when creating a new scratch org with sfdx-hardis

+
+ + + + + +
+
Examples:
+
true
+
+
false
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Package installation key

Type: string
+

Installation key for key-protected package

+
+ + + + + +
+
Examples:
+
"MyInstallationKey"
+
+
"4FzkMzUSwFfP#@"
+
+
+
+
+
+
+
+

+
Example:
+
[
+    {
+        "Id": "0A30N000000ALWrSAO",
+        "SubscriberPackageId": "033b0000000Pf2AAAS",
+        "SubscriberPackageName": "Declarative Lookup Rollup Summaries Tool",
+        "SubscriberPackageNamespace": "dlrs",
+        "SubscriberPackageVersionId": "04t0N000000IyYrQAK",
+        "SubscriberPackageVersionName": "2.11",
+        "SubscriberPackageVersionNumber": "2.11.0.1",
+        "installOnScratchOrgs": false,
+        "installDuringDeployments": true,
+        "installationkey": "MyInstallationKey"
+    },
+    {
+        "Id": "0A35r000000GveVCAS",
+        "SubscriberPackageId": "0330o000000B3vIAAS",
+        "SubscriberPackageName": "Files Attachment Notes",
+        "SubscriberPackageNamespace": "fan_astrea",
+        "SubscriberPackageVersionId": "04t0o000003nRWAAA2",
+        "SubscriberPackageVersionName": "Summer2021",
+        "SubscriberPackageVersionNumber": "1.22.0.2",
+        "installOnScratchOrgs": true,
+        "installDuringDeployments": true
+    }
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Install packages during deployment checks

Type: boolean Default: false
+

When calling deployment check command, installs any package referred within installedPackages property

+
+ + + + + +
+
Example:
+
true
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Instance URL

Type: string Default: ""
+

Salesforce instance URL used by CI for deployment or backups

+
+ + + + + +
+
Examples:
+
"https://myclient.force.com"
+
+
"https://google.force.com"
+
+
"https://apple.force.com"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

List views to set to Mine

Type: array of string Default: []
+

List of ListView items to set to Mine after a delivery (that does not accept value 'Everything')

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Metadata to retrofit

Type: array of string
+

List of metadata to retrieve for retrofit job

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+

+
Example:
+
[
+    "CustomField",
+    "Layout",
+    "PermissionSet"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Monitoring commands

Type: array of object
+

List of monitoring commands to run with command hardis:org:monitor:all

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: object
+

Monitoring command

+
No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ +

Key

Type: string
+

Unique identifier of the monitoring command. Can be used with monitoringDisable

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Title

Type: string
+

Title of the command (will appear in logs)

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Command

Type: string
+

Bash command to run

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Frequency

Type: string
+

daily or weekly

+
+ + + + + + +
+
+
+
+
+

+
Example:
+
[
+    {
+        "title": "Detect calls to deprecated API versions",
+        "key": "LEGACYAPI",
+        "command": "sf hardis:org:diagnose:legacyapi",
+        "frequency": "weekly"
+    },
+    {
+        "title": "My custom command",
+        "key": "MY_CUSTOM_KEY",
+        "command": "sf my:custom:command",
+        "frequency": "daily"
+    }
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Monitoring Allowed Sections Actions

Type: object
+

Override list of Setup Audit Trail elements that won't be considered as suspect by monitoring tools

+
+ + + + + + +
+
+
+

+ +

+
+ +
+

Additional Properties of any type are allowed.

+ + Type: object
+ + + + + + + +
+
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Disabled monitoring commands

Type: array
+

List of commands to skip during monitoring jobs

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: enum (of string)
+ + +
+

Must be one of:

+
  • "AUDIT_TRAIL"
  • "LEGACY_API"
  • "LINT_ACCESS"
  • "UNUSED_METADATAS"
  • "METADATA_STATUS"
  • "MISSING_ATTRIBUTES"
  • "UNUSED_LICENSES"
  • "RELEASE_UPDATES"
+
+ + + + + + +
+

+
Example:
+
[
+    "METADATA_STATUS",
+    "UNUSED_METADATAS"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Monitoring usernames to exclude

Type: array of string
+

List of usernames to exclude while running monitoring commands

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+

+
Example:
+
[
+    "deploymentuser@cloudity.com",
+    "mc-cloud-user@cloudity.com"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

MsTeams WebHook Url (ALL)

Type: string Default: ""
+

Url of the Ms Teams channel Web Hook that can be used to send ALL notifications

+
+ + + + + +
+
Example:
+
"https://my.msteams.webhook.url"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

MsTeams WebHook Url (CRITICAL)

Type: string Default: ""
+

Url of the Ms Teams channel Web Hook that can be used to send CRITICAL notifications

+
+ + + + + +
+
Example:
+
"https://my.msteams.webhook.url"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

MsTeams WebHook Url (SEVERE)

Type: string Default: ""
+

Url of the Ms Teams channel Web Hook that can be used to send SEVERE notifications

+
+ + + + + +
+
Example:
+
"https://my.msteams.webhook.url"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

MsTeams WebHook Url (WARNING)

Type: string Default: ""
+

Url of the Ms Teams channel Web Hook that can be used to send WARNING notifications

+
+ + + + + +
+
Example:
+
"https://my.msteams.webhook.url"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

MsTeams WebHook Url (INFO)

Type: string Default: ""
+

Url of the Ms Teams channel Web Hook that can be used to send INFO notifications

+
+ + + + + +
+
Example:
+
"https://my.msteams.webhook.url"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Disabled notification types

Type: array
+

List of notifications types to skip sending

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: enum (of string)
+ + +
+

Must be one of:

+
  • "AUDIT_TRAIL"
  • "APEX_TESTS"
  • "BACKUP"
  • "DEPLOYMENT"
  • "LEGACY_API"
  • "LINT_ACCESS"
  • "UNUSED_METADATAS"
  • "METADATA_STATUS"
  • "MISSING_ATTRIBUTES"
  • "UNUSED_LICENSES"
  • "RELEASE_UPDATES"
+
+ + + + + + +
+

+
Example:
+
[
+    "METADATA_STATUS",
+    "UNUSED_METADATAS"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Package-No-Overwrite path

Type: string Default: ""
+

Path to a custom package-no-overwrite XML file (used in smartDeploy command)

+
+ + + + + +
+
Examples:
+
"manifest/package-no-overwrite-main.xml"
+
+
"manifest/package-no-overwrite-custom.xml"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Scratch org pool configuration

Type: object
+

Configuration allowing to generate and fetch scratch orgs from scratch org pool

+
+ + + + + +
+
Example:
+
{
+    "maxScratchOrgsNumber": 10,
+    "storageService": "kvdb.io"
+}
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Min scratch org remaining days

Type: number Default: 25
+

When pool scratch org is less than this number, it is deleted and another one is created

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Maximum number of scratch orgs

Type: number
+

Maximum number of active scratch orgs in the scratch org pool

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Maximum number of scratch orgs to create once

Type: number
+

Maximum number of scratch orgs to create in one CI job

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Storage service for scratch org pool

Type: string
+

Remote service allowing to store scratch org pool details

+
+ + + + + + +
+
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Production branch name

Type: string Default: ""
+

Name of the git branch corresponding to production environment

+
+ + + + + +
+
Examples:
+
"master"
+
+
"main"
+
+
"production"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Project Name

Type: string Default: ""
+

Identifier for the project (can be the client and project)

+
+ + + + + +
+
Examples:
+
"MyClientMyProject"
+
+
"GoogleGmail"
+
+
"AppleIWatch"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Retrofit branch name

Type: string Default: ""
+

Name of the git branch where retrofit merge requests targets to

+
+ + + + + +
+
Examples:
+
"preprod"
+
+
"dev"
+
+
"maintenance"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Retrofit ignored files

Type: array of string
+

When calling hardis:org:retrieve:sources:retrofit, list of files to ignore (discard just after retrieve)

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+

+
Example:
+
[
+    "force-app/main/default/applications/MyAppIWantToManageInProduction.app-meta.xml",
+    "force-app/main/default/flexipages/MyFlexipageWithDashboards.flexipage-meta.xml"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Selected tests to run (list or regex)

Type: string Default: ""
+

WARNING: Use with caution, only in branch scoped config ! Can be a list of test classes if testLevel=RunSpecifiedTests, or a regex if testLevel=RunRepositoryTests

+
+ + + + + +
+
Examples:
+
"MyTestClass1,MyTestClass2"
+
+
"^(?!FLI|fli|BatchableCodeSolvaTest|BatchableRemoveCodeSolvaTest|HelperNovaxelApiTest).*"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Scratch org init apex scripts

Type: array of string
+

Apex scripts to call after scratch org initialization

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+

+
Example:
+
[
+    "scripts/apex/init-scratch.apex",
+    "scripts/apex/init-custom-settings.apex"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Duration of Scratch Org

Type: number Default: 30
+

Defines the lifespan of the scratch org in number of days, from 1 to 30

+
+ + + +

Value must be greater or equal to 1 and lesser or equal to 30

+ + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

SFDMU can modify

Type: string Default: ""
+

Instance host name to allow SFDMU to deploy data in a production org

+
+ + + + + +
+
Example:
+
"myproject.force.com"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Skip code coverage check

Type: boolean Default: false
+

WARNING: Use with caution, only in branch scoped config ! Do not check code coverage for a deployment

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Skip Minimize Profiles

Type: array of string
+

These profiles will not be reformatted by command hardis:project:clean:minimizeprofiles

+
+ + + + + + No Additional Items

Each item of this array must be:

+
+
+ + + Type: string
+ + + + + + + +
+

+
Example:
+
[
+    "MyClient Customer Community Login User",
+    "MyClientPortail Profile"
+]
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Skip update .forceignore file

Type: boolean Default: false
+

Defines if sfdx-hardis will propose to upgrade local .forceignore file

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Skip update .gitignore file

Type: boolean Default: false
+

Defines if sfdx-hardis will propose to upgrade local .gitignore file

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Target Username

Type: string Default: ""
+

Salesforce username used by CI for deployment or backups

+
+ + + + + +
+
Examples:
+
"deployments@myclient.com"
+
+
"deployments@google.fr"
+
+
"deployments@apple.com"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Test Coverage not blocking

Type: boolean Default: false
+

Does not make the deployment job fail if apex tests code coverage is failing

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Test level for deployments

Type: enum (of string) Default: "RunLocalTests"
+

WARNING: Use with caution, only in branch scoped config ! You can override default test level for deployments for special use cases, for example when you have SeeAllData=true you can use RunRepositoryTests associated with a regex in runtests option

+
+

Must be one of:

+
  • "NoTestRun"
  • "RunSpecifiedTests"
  • "RunRepositoryTests"
  • "RunRepositoryTestsExceptSeeAllData"
  • "RunLocalTests"
  • "RunAllTestsInOrg"
+
+ + + + + +
+
Examples:
+
"RunRepositoryTests"
+
+
"RunSpecifiedTests"
+
+
+
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Use Delta Deployment

Type: boolean Default: false
+

Defines if sfdx-hardis will deploy in delta from minor to major branches

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Use Smart Deployment Tests

Type: boolean Default: false
+

Define if smart deployment tests will be activated and run test classes only if necessary (see more in hardis:project:deploy:smart documentation

+
+ + + + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ +

Linter ignore permission set or/and profile

Type: string Default: ""
+

Ignore profiles or permission sets

+
+ + + + + +
+
Examples:
+
"Profile"
+
+
"Profile:ProfileA"
+
+
"PermissionSet"
+
+
"PermissionSet:PermissionSetA, Profile:ProfileA"
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 000000000..e1bb60cb2 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":""},{"location":"#sfdx-hardis","title":"sfdx-hardis","text":"

Presented at Dreamforce 23 and Dreamforce 24!

Toolbox for Salesforce DX, by Cloudity & friends, natively compliant with most platforms and tools.

It will allow you to:

  • Do with simple commands what could be done manually in minutes/hours
  • Define a ready to use CI/CD Pipeline for your Salesforce project
  • Backup Metadatas and monitor any Salesforce org

Please see the full list of commands in Online documentation

sfdx-hardis commands are also available with UI in SFDX Hardis Visual Studio Code Extension

See Dreamforce presentation

"},{"location":"#installation","title":"Installation","text":""},{"location":"#with-ide","title":"With IDE","text":"

You can install Visual Studio Code extension VsCode SFDX Hardis

Once installed, click on in VsCode left bar, and follow the additional installation instructions

"},{"location":"#as-sfdx-plugin","title":"As SFDX Plugin","text":""},{"location":"#pre-requisites","title":"Pre-requisites","text":"
  • Install Node.js (recommended version)
  • Install Salesforce DX by running npm install @salesforce/cli --global command line
"},{"location":"#plugin-installation","title":"Plugin installation","text":"
sf plugins install sfdx-hardis\n

For advanced use, please also install dependencies

sf plugins install @salesforce/plugin-packaging\nsf plugins install sfdmu\nsf plugins install sfdx-git-delta\nsf plugins install texei-sfdx-plugin\n

If you are using CI/CD scripts, use echo y | sf plugins install ... to bypass prompt.

"},{"location":"#docker","title":"Docker","text":"

You can use sfdx-hardis docker images to run in CI

  • Docker Hub

    • hardisgroupcom/sfdx-hardis:latest (with latest @salesforce/cli version)
    • hardisgroupcom/sfdx-hardis:latest-sfdx-recommended (with recommended @salesforce/cli version, in case the latest version of @salesforce/cli is buggy)
  • GitHub Packages (ghcr.io)
    • ghcr.io/hardisgroupcom/sfdx-hardis:latest (with latest @salesforce/cli version)
    • ghcr.io/hardisgroupcom/sfdx-hardis:latest-sfdx-recommended (with recommended @salesforce/cli version, in case the latest version of @salesforce/cli is buggy)

See Dockerfile

"},{"location":"#usage","title":"Usage","text":"
sf hardis:<COMMAND> <OPTIONS>\n
"},{"location":"#articles","title":"Articles","text":"

Here are some articles about sfdx-hardis

  • English

  • French
    • Versions d'API Salesforce d\u00e9commissionn\u00e9es: Que faire ?
    • Exporter en masse les fichiers d\u2019une org Salesforce
    • Suspendre l\u2019acc\u00e8s aux utilisateurs lors d\u2019une mise en production Salesforce
"},{"location":"#contributing","title":"Contributing","text":"

Everyone is welcome to contribute to sfdx-hardis (even juniors: we'll assist you !)

  • Install Node.js (recommended version)
  • Install typescript by running npm install typescript --global
  • Install yarn by running npm install yarn --global
  • Install Salesforce DX by running npm install @salesforce/cli --global command line
  • Fork this repo and clone it (or just clone if you are an internal contributor)
  • At the root of the repository:
    • Run yarn to install dependencies
    • Run sf plugins link to link the local sfdx-hardis to SFDX CLI
    • Run tsc --watch to transpile typescript into js everytime you update a TS file
  • Debug commands using NODE_OPTIONS=--inspect-brk sf hardis:somecommand -someparameter somevalue
"},{"location":"#dependencies","title":"Dependencies","text":"

sfdx-hardis partially relies on the following SFDX Open-Source packages

  • Salesforce Data Move Utility
  • SFDX Git Delta
  • Texei Sfdx Plugin
"},{"location":"#contributors","title":"Contributors","text":""},{"location":"#commands","title":"Commands","text":""},{"location":"#hardisauth","title":"hardis:auth","text":"Command Title hardis:auth:login"},{"location":"#hardiscache","title":"hardis:cache","text":"Command Title hardis:cache:clear"},{"location":"#hardisconfig","title":"hardis:config","text":"Command Title hardis:config:get"},{"location":"#hardisdeploy","title":"hardis:deploy","text":"Command Title hardis:deploy:quick hardis:deploy:start hardis:deploy:validate"},{"location":"#hardisdoc","title":"hardis:doc","text":"Command Title hardis:doc:extract:permsetgroups hardis:doc:flow2markdown hardis:doc:mkdocs-to-salesforce hardis:doc:packagexml2markdown hardis:doc:plugin:generate hardis:doc:project2markdown"},{"location":"#hardisgit","title":"hardis:git","text":"Command Title hardis:git:pull-requests:extract"},{"location":"#hardislint","title":"hardis:lint","text":"Command Title hardis:lint:access hardis:lint:metadatastatus hardis:lint:missingattributes hardis:lint:unusedmetadatas"},{"location":"#hardismdapi","title":"hardis:mdapi","text":"Command Title hardis:mdapi:deploy"},{"location":"#hardismisc","title":"hardis:misc","text":"Command Title hardis:misc:purge-references hardis:misc:toml2csv"},{"location":"#hardisorg","title":"hardis:org","text":"Command Title hardis:org:community:update hardis:org:configure:data hardis:org:configure:files hardis:org:configure:monitoring hardis:org:connect hardis:org:create hardis:org:data:delete hardis:org:data:export hardis:org:data:import hardis:org:diagnose:audittrail hardis:org:diagnose:instanceupgrade hardis:org:diagnose:legacyapi hardis:org:diagnose:licenses hardis:org:diagnose:releaseupdates hardis:org:diagnose:unused-apex-classes hardis:org:diagnose:unused-connected-apps hardis:org:diagnose:unusedlicenses hardis:org:diagnose:unusedusers hardis:org:files:export hardis:org:files:import hardis:org:fix:listviewmine hardis:org:generate:packagexmlfull hardis:org:monitor:all hardis:org:monitor:backup hardis:org:monitor:limits hardis:org:multi-org-query hardis:org:purge:apexlog hardis:org:purge:flow hardis:org:retrieve:packageconfig hardis:org:retrieve:sources:analytics hardis:org:retrieve:sources:dx hardis:org:retrieve:sources:dx2 hardis:org:retrieve:sources:metadata hardis:org:retrieve:sources:retrofit hardis:org:select hardis:org:test:apex hardis:org:user:activateinvalid hardis:org:user:freeze hardis:org:user:unfreeze"},{"location":"#hardispackage","title":"hardis:package","text":"Command Title hardiscreate hardisinstall hardismergexml hardisversion:create hardisversion:list hardisversion:promote"},{"location":"#hardispackagexml","title":"hardis:packagexml","text":"Command Title hardis:packagexml:append hardis:packagexml:remove"},{"location":"#hardisproject","title":"hardis:project","text":"Command Title hardis:project:audit:apiversion hardis:project:audit:callincallout hardis:project:audit:duplicatefiles hardis:project:audit:remotesites hardis:project:clean:emptyitems hardis:project:clean:filter-xml-content hardis:project:clean:flowpositions hardis:project:clean:hiddenitems hardis:project:clean:listviews hardis:project:clean:manageditems hardis:project:clean:minimizeprofiles hardis:project:clean:orgmissingitems hardis:project:clean:references hardis:project:clean:retrievefolders hardis:project:clean:sensitive-metadatas hardis:project:clean:standarditems hardis:project:clean:systemdebug hardis:project:clean:xml hardis:project:configure:auth hardis:project:convert:profilestopermsets hardis:project:create hardis:project:deploy:notify hardis:project:deploy:quick hardis:project:deploy:simulate hardis:project:deploy:smart hardis:project:deploy:sources:dx hardis:project:deploy:sources:metadata hardis:project:deploy:start hardis:project:deploy:validate hardis:project:fix:profiletabs hardis:project:fix:v53flexipages hardis:project:generate:flow-git-diff hardis:project:generate:gitdelta hardis:project:lint hardis:project:metadata:findduplicates"},{"location":"#hardisscratch","title":"hardis:scratch","text":"Command Title hardis:scratch:create hardis:scratch:delete hardis:scratch:pool:create hardis:scratch:pool:localauth hardis:scratch:pool:refresh hardis:scratch:pool:reset hardis:scratch:pool:view hardis:scratch:pull hardis:scratch:push"},{"location":"#hardissource","title":"hardis:source","text":"Command Title hardis:source:deploy hardis:source:push hardis:source:retrieve"},{"location":"#hardiswork","title":"hardis:work","text":"Command Title hardis:work:new hardis:work:refresh hardis:work:resetselection hardis:work:save hardis:work:ws"},{"location":"#helloworld","title":"hello:world","text":"Command Title hello:world"},{"location":"CHANGELOG/","title":"Changelog","text":""},{"location":"CHANGELOG/#beta-master","title":"[beta] (master)","text":"

Note: Can be used with sfdx plugins:install sfdx-hardis@beta and docker image hardisgroupcom/sfdx-hardis@beta

  • New command hardis:doc:mkdocs-to-salesforce to generate static HTML doc and host it in a Static Resource and a VisualForce page
  • Remove hyperlinks from MermaidJs on Pull Request comments, to improve display on GitHub & Gitlab
  • Upgrade base image to python:3.12.8-alpine3.20, so mkdocs can be installed and run if necessary
"},{"location":"CHANGELOG/#5110-2025-01-03","title":"[5.11.0] 2025-01-03","text":"
  • Visual flow management, using MermaidJs
    • hardis:doc:project2markdown: Add a markdown file for each Flow
      • If unable to run mermaid-cli, store markdown with mermaidJs diagram content anyway (can happen from Monitoring Backup Command)
      • When called from Monitoring (hardis:org:monitor:backup), generate Flow documentation only if it has been updated
    • hardis:doc:flow2markdown: Generate the markdown documentation of a single flow (available from VsCode extension)
    • hardis:project:generate:flow-git-diff: Generate the visual git diff for a single flow (available from VsCode extension)
    • hardis:project:deploy:smart: Add visual git diff for flows updated by a Pull Request
    • Flow Visual Git diff also added to standard SF Cli commands wrappers
  • New command hardis:project:deploy:notify to send Pull Request comments (with Flow Visual Git Diff) and Slack / Teams notifications even if you are not using a sfdx-hardis command to check or process a deployment.
  • Command updates
    • hardis:project:deploy:smart: Refactor deployment errors parsing: use JSON output instead of text output
    • hardis:org:test:apex: Display the number of failed tests in messages and notifications
    • hardis:org:monitor:backup:
      • New option --exclude-namespaces that can be used with --full option
      • New option --full-apply-filters that can be used with --full option to apply filters anyway
  • Core enhancements & fixes
    • Obfuscate some data from text log files
    • Kill some exit handlers in case they are making the app crash after a throw SfError
    • Trigger notifications during the command execution, not after
    • Do not display warning in case no notification has been configured in case we are running locally
    • Fix Individual deployment tips markdown docs by adding quotes to YML properties
    • Fix init sfdx-hardis project commands and docs
    • Display warning message in case package.xml has wrong format
    • Allow to override package-no-overwrite from a branch .sfdx-hardis.yml config file
    • Using target_branch for Jira labels when isDeployBeforeMerge flag is true
  • Doc
    • Update Microsoft Teams notifications integration User Guide
    • Add troubleshooting section in Email integration User Guide
"},{"location":"CHANGELOG/#5101-2024-12-12","title":"[5.10.1] 2024-12-12","text":"
  • Fix sfdx-hardis docker image build by adding coreutils in dependencies
"},{"location":"CHANGELOG/#5100-2024-12-12","title":"[5.10.0] 2024-12-12","text":"
  • Update Docker base image to alpine to 3.21
"},{"location":"CHANGELOG/#593-2024-12-12","title":"[5.9.3] 2024-12-12","text":"
  • hardis:org:data:import: Allow to run the command in production using, by either:
    • Define sfdmuCanModify in your .sfdx-hardis.yml config file. (Example: sfdmuCanModify: prod-instance.my.salesforce.com)
    • Define an environment variable SFDMU_CAN_MODIFY. (Example: SFDMU_CAN_MODIFY=prod-instance.my.salesforce.com)
"},{"location":"CHANGELOG/#592-2024-12-10","title":"[5.9.2] 2024-12-10","text":"
  • Fallback message in case sfdx-hardis is not able to parse newest SF CLI errors format.
"},{"location":"CHANGELOG/#591-2024-12-09","title":"[5.9.1] 2024-12-09","text":"
  • Fix issue that generates valid Pull Request comment whereas there is 1 error
  • Add TS test case
  • Upgrade NPM dependencies
"},{"location":"CHANGELOG/#590-2024-12-02","title":"[5.9.0] 2024-12-02","text":"
  • hardis:org:monitor:backup: New mode --full, much slower than default filtered one, but that can retrieve ALL metadatas of an org
"},{"location":"CHANGELOG/#581-2024-11-26","title":"[5.8.1] 2024-11-26","text":"
  • Fix hardis:org:diagnose:unused-apex-classes: Use .cls file, not cls-meta.xml file to get creation date from git
"},{"location":"CHANGELOG/#580-2024-11-25","title":"[5.8.0] 2024-11-25","text":"
  • New monitoring command hardis:org:diagnose:unused-connected-apps to detect Connected Apps that are not used anymore and might be disabled or deleted.
"},{"location":"CHANGELOG/#572-2024-11-25","title":"[5.7.2] 2024-11-25","text":"
  • Fix issue with auth just before running a command (ask to run again the same command meanwhile we find a way to avoid that using SF CLI architecture)
"},{"location":"CHANGELOG/#571-2024-11-22","title":"[5.7.1] 2024-11-22","text":"
  • In case a prompt is requested during CI and makes a command fail, display the content of the prompt
"},{"location":"CHANGELOG/#570-2024-11-22","title":"[5.7.0] 2024-11-22","text":"
  • New command hardis:git:pull-requests:extract: Extract Pull Requests from Git Server into CSV/XLS (Azure only for now)
  • Fix bug when scratch org username is > 80 chars
  • Make markdown-links-check not blocking by default in MegaLinter base config
  • Make yamllint not blocking by default in MegaLinter base config
"},{"location":"CHANGELOG/#563-2024-11-17","title":"[5.6.3] 2024-11-17","text":"
  • MegaLinter config: disable APPLY_FIXES by default
  • Upgrade npm dependencies
"},{"location":"CHANGELOG/#562-2024-11-12","title":"[5.6.2] 2024-11-12","text":"
  • hardis:org:diagnose:unused-apex-classes
    • Display class created by and created name MIN(date from org,date from git)
    • Replace errors by warnings, and add a message so users double-check before removing a class
    • Reorder console log
  • Remove unused code from MetadataUtils class
"},{"location":"CHANGELOG/#561-2024-11-11","title":"[5.6.1] 2024-11-11","text":"
  • Fix hardis:org:user:activateinvalid interactive mode
  • Update Dockerfile email address
  • Upgrade default Grafana Dashboards to add Unused Apex Classes indicator
  • Update hardis:org:diagnose:unused-apex-classes and hardis:doc:packagexml2markdown documentation
"},{"location":"CHANGELOG/#560-2024-11-09","title":"[5.6.0] 2024-11-09","text":"
  • New command hardis:org:diagnose:unused-apex-classes, to detect Apex classes (Batch,Queueable,Schedulable) that has not been called for more than 365 days, that might be deleted to improve apex tests performances
  • hardis:doc:project2markdown: Update documentation
  • Polish CI/CD home doc
  • Refactor the build of hardis:org:monitor:all documentation
  • Fix issue with ToolingApi calls: handle paginated results instead of only the first 200 records.
"},{"location":"CHANGELOG/#550-2024-11-03","title":"[5.5.0] 2024-11-03","text":"
  • hardis:doc:packagexml2markdown: Generate markdown documentation from a package.xml file
  • hardis:doc:project2markdown: Generate markdown documentation from any SFDX project (CI/CD, monitoring, projects not using sfdx-hardis...) in docs folder and add a link in README.md if existing.
  • hardis:org:monitor:backup: Call hardis:doc:project2markdown after backup
  • hardis:org:retrieve:packageconfig: Ignore standard Salesforce packages
  • Update CI/CD home documentation
"},{"location":"CHANGELOG/#541-2024-11-02","title":"[5.4.1] 2024-11-02","text":"
  • hardis:org:multi-org-query enhancements
    • Improve documentation
    • Allow to use --query-template as option to use one of the predefined templates via command line
    • Handle errors if issues when the command is called via a CI/CD job
  • Upgrade dependencies
"},{"location":"CHANGELOG/#540-2024-11-02","title":"[5.4.0] 2024-11-02","text":"
  • New command hardis:org:multi-org-query allowing to execute a SOQL Bulk Query in multiple orgs and aggregate the results in a single CSV / XLS report
  • New command hardis:org:community:update to Activate / Deactivate communities from command line
"},{"location":"CHANGELOG/#530-2024-10-24","title":"[5.3.0] 2024-10-24","text":"
  • Update default Monitoring workflow for GitHub
  • Refactor file download code
    • Display progress
    • Better error handling
  • hardis:org:diagnose:legacyapi: Fix issue with big log files: Use stream to parse CSV and perform checks
  • Update default API version toto 62.0 (Winter 25 release)
"},{"location":"CHANGELOG/#524-2024-10-21","title":"[5.2.4] 2024-10-21","text":"
  • Fix hardis:org:fix:listviewmine: Use chrome-launcher to find chrome executable to use with puppeteer-core
  • Remove keyv dependency
"},{"location":"CHANGELOG/#523-2024-10-19","title":"[5.2.3] 2024-10-19","text":"
  • Change default .mega-linter.yml config
  • Display number of package.xml items before or after retrieving them
  • Doc: Update youtube preview images
"},{"location":"CHANGELOG/#522-2024-10-14","title":"[5.2.2] 2024-10-14","text":"
  • Fix doubling -d option in hardis:scratch:create
"},{"location":"CHANGELOG/#521-2024-10-14","title":"[5.2.1] 2024-10-14","text":"
  • 2 hardis commands: rename -d into something else when the short option was available twice on the same command
"},{"location":"CHANGELOG/#520-2024-10-14","title":"[5.2.0] 2024-10-14","text":"
  • Improve BUILD & RUN documentation
  • 21 hardis commands: rename -o short into -f when possible, or other short letter, to avoid collision with -o (--target-org) option
  • Fix GitHub Org Monitoring workflow (remove push event + fix command typo)
"},{"location":"CHANGELOG/#510-2024-10-11","title":"[5.1.0] 2024-10-11","text":"
  • hardis:project:deploy:smart: Fix to adapt stdout checks to output of sf project deploy start in case code coverage is ignored
  • hardis:org:monitor:backup: Allow spaces in folders
  • Remove pubsub from default .forceignore
  • Change default deployment waiting time from 60mn to 120mn
  • Display explicit warning message before ConnectedApp deployment so users don't forget to manually create the connected app with the certificate
"},{"location":"CHANGELOG/#5010-2024-10-03","title":"[5.0.10] 2024-10-03","text":"
  • hardis:project:deploy:smart : Fix parsing of error strings
  • hardis:project:deploy:smart : Fix markdown display on PR summary
"},{"location":"CHANGELOG/#509-2024-10-03","title":"[5.0.9] 2024-10-03","text":"
  • Fix link to tip doc from Pull Request / Merge Request comments
  • Fixing small issues with creating scratch org and scratch org pool
"},{"location":"CHANGELOG/#508-2024-10-01","title":"[5.0.8] 2024-10-01","text":"
  • Monitoring config: Fix way to define how to upload connected app
  • New deployment tip: Couldn't retrieve or load information on the field
  • Fix parsing of errors when they are unknown
  • Fix SEO info in deployment tips documentation
"},{"location":"CHANGELOG/#507-2024-09-25","title":"[5.0.7] 2024-09-25","text":"
  • hardis:org:monitoring:backup : fix issue when metadata type is unknown
"},{"location":"CHANGELOG/#506-2024-09-25","title":"[5.0.6] 2024-09-25","text":"
  • Allow to purge flows & flow interviews using --no-prompt option
  • Fix duplicate -f short option by replacing delete-flow-interviews short by -w
"},{"location":"CHANGELOG/#505-2024-09-24","title":"[5.0.5] 2024-09-24","text":"
  • When git add / stash failure, display a message explaining to run git config --system core.longpaths true to solve the issue.
  • Improve test classes errors collection during deployment check
  • Display the number of elements deployed within a package.xml
"},{"location":"CHANGELOG/#504-2024-09-24","title":"[5.0.4] 2024-09-24","text":"
  • Fix errors collection during deployment check
  • Display in deployment check summary when useSmartDeploymentTests has been activated
  • Do not send coverage formatters options when test level is NoTestRun
"},{"location":"CHANGELOG/#503-2024-09-23","title":"[5.0.3] 2024-09-23","text":"
  • Add --ignore-conflicts to smartDeploy
"},{"location":"CHANGELOG/#502-2024-09-23","title":"[5.0.2] 2024-09-23","text":"
  • Always use project deploy start --dry-run for deployment validation, until command project deploy validate works with --ignore-warnings & NoTestRun
"},{"location":"CHANGELOG/#500-2024-09-23","title":"[5.0.0] 2024-09-23","text":""},{"location":"CHANGELOG/#refactoring-explanations","title":"Refactoring explanations","text":"

The future deprecation of sfdx force:source:** commands on 6 november finally convinced us to switch everything from SFDX core to SF CLI core. (otherwise existing CI/CD pipelines would not work anymore from this date !)

Therefore, sfdx-hardis required a complete refactoring as described below, but this won't impact existing CI/CD and Monitoring pipelines.

We made many tests but risk zero do not exist, so if you see any bug, please report them ASAP and we'll solve them quickly :)

"},{"location":"CHANGELOG/#major-changes","title":"Major changes","text":"
  • Migrate plugin from SFDX plugin core to SF Cli Plugin core

    • Convert commands code from SfdxCommand base to SfCommand base
    • Migrate internal Bulk Api calls from Bulk API v1 to Bulk API v2
    • Upgrade all npm dependencies to their latest version (more secured)
  • Change background calls to legacy sfdx commands to call their SF Cli replacements

    • sfdx force:mdapi:convert -> sf project convert mdapi
    • sfdx force:mdapi:deploy -> sf project deploy start --metadata-dir
    • sfdx force:source:retrieve -> sf project retrieve start
    • sfdx force:source:deploy -> sf project deploy start
    • sfdx force:source:pull -> sf project retrieve start
    • sfdx force:source:push -> sf project deploy start
    • sfdx force:source:tracking:clear -> sf project delete tracking
    • sfdx force:source:manifest:create -> sf project generate manifest
    • sfdx sgd:source:delta -> sf sgd:source:delta
    • sfdx force:org:create -> sf org create sandbox | sf org create scratch
    • sfdx force:org:list -> sf org list
    • sfdx force:org:delete -> sf org delete scratch
    • sfdx config:get -> sf config get
    • sfdx config:set -> sf config set
    • sfdx auth:web:login -> sf org login web
    • sfdx auth:jwt:grant -> sf org login jwt
    • sfdx auth:sfdxurl:store -> sf org login sfdx-url
    • sfdx org:login:device -> sf org login device
    • sfdx force:data:record:get -> sf data get record
    • sfdx force:data:record:update -> sf data update record
    • sfdx force:data:soql:query -> sf data query
    • sfdx force:data:bulk:delete -> sf data delete bulk
    • sfdx alias:list -> sf alias list
    • sfdx alias:set -> sf alias set
    • sfdx force:apex:test:run -> sf apex run test
    • sfdx force:apex:execute -> sf apex run
    • sfdx force:package:create -> sf package create
    • sfdx force:package:version:create -> sf package version create
    • sfdx force:package:version:delete -> sf package version delete
    • sfdx force:package:version:list -> sf package version list
    • sfdx force:package:version:promote -> sf package version promote
    • sfdx force:package:installed:list -> sf package installed
    • sfdx force:package:install -> sf package install
    • sfdx force:user:password:generate -> sf org generate password
    • sfdx force:user:permset:assign -> sf org assign permset
    • sfdx hardis:_ -> sf hardis:_
  • New wrappers commands for SF Cli deployment commands
    • sf hardis project deploy validate -> Wraps sf project deploy validate
    • sf hardis project deploy quick -> Wraps sf project deploy quick
    • sf hardis project deploy start -> Wraps sf project deploy start
"},{"location":"CHANGELOG/#new-features-enhancements","title":"New Features / Enhancements","text":"
  • hardis:project:deploy:smart
    • New feature useSmartDeploymentTests: Improve performances by not running test classes when delta deployment contain only non impacting metadatas, and target org is not production
    • Rename command hardis:project:deploy:source:dx into hardis:project:deploy:smart (previous command alias remains, no need to update your pipelines !)
  • commandsPreDeploy and commandsPostDeploy
    • New option context for a command, defining when it is run and when it is not: all (default), check-deployment-only or process-deployment-only
    • New option runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)
  • New commands
    • hardis:project:deploy:simulate to validate the deployment of a single metadata (used by VsCode extension)
    • hardis:org:diagnose:releaseupdates to check for org Release Updates from Monitoring or locally
    • hardis:misc:purge-references to partially automate the cleaning of related dependencies when you need to delete a field, or change its type (for example from master detail to lookup)
    • hardis:project:clean:sensitive-metadatas to mask sensitive metadatas from git repo (ex: Certificate content)
  • hardis:work:save and hardis:project:deploy:sources:dx: Improve runtime performances thanks to internalization of sfdx-essentials commands
  • hardis:work:new
    • Allow to add labels in property availableTargetBranches, using a comma. For examples, - integration,Choose this branch if you are on the BUILD side of the project !
    • Add current default org in the choices when prompting which org to use
  • hardis:project:new
    • Initialize autoCleanTypes with destructivechanges, flowPositions and minimizeProfiles
    • Initialize package-no-overwrite.xml with Certificate metadata. (certificates must be uploaded manually)
  • hardis:org:files:export: Improve display with spinner
  • hardis:org:purge:flow: If FlowInterview records are preventing Flow Versions to be deleted, prompt user to delete Flow Interviews before trying again to delete Flow Versions
  • hardis:project:generate:gitdelta: Add option to generate package.xml related to a single commit
  • hardis:org:data:delete: Check for property \"runnableInProduction\" in export.json before running deletion in production org.
  • hardis:org:diagnose:audittrail: Add new filtered actions
    • Customer Portal: createdcustomersuccessuser
  • Authentication: do not use alias MY_ORG anymore + do not update local user config if no values to replace.
  • When selecting an org, make sure it is still connected. If not, open browser so the user can authenticate again.
  • Update sfdx-hardis Grafana Dashboards to import in your Grafana Cloud
    • SF Instance name
    • Next platform upgrade
    • Release Updates to check
    • Installed packages
    • Org licenses
  • AI Deployment assistant
    • Add error Change Matching Rule
  • Git Providers
    • On Pull Requests / Merge Requests comments, add hyperlinks to errors documentation URL
"},{"location":"CHANGELOG/#fixes","title":"Fixes","text":"
  • Avoid error when removing obsolete flows (workaround using SF CLI if tooling api connection fails). Fixes #662
  • Improve Slack/Teams notifications display
  • Display explicit error message in case a password is required to install a managed package.
"},{"location":"CHANGELOG/#documentation","title":"Documentation","text":"
  • Reorganize README content
    • Add link to Dreamforce 24 session
  • Deployment assistant: Improve documentation by adding examples of errors, and a standalone page for each tip
  • Factorize the definition of DOC_ROOT_URL https://sfdx-hardis.cloudity.com
"},{"location":"CHANGELOG/#deprecations","title":"Deprecations","text":"
  • Deprecate wrapper commands matching sfdx commands that will be removed. All replaced by sf hardis deploy start

    • sfdx hardis:source:push
    • sfdx hardis:source:deploy
    • sfdx hardis:mdapi:retrieve
    • sfdx hardis:mdapi:deploy
  • Deprecate hardis:deploy:sources:metadata as nobody uses metadata format anymore
"},{"location":"CHANGELOG/#removals","title":"Removals","text":"
  • Replace puppeteer by puppeteer-core: it means that if you use a command requiring puppeteer, please make sure to have a Chrome available in your environment (already integrated within the Docker image)
  • Get rid of sfdx-essentials plugin dependency by internalizing its used commands

    • sf hardis:packagexml:append
    • sf hardis:packagexml:remove
    • sf hardis:project:clean:filter-xml-content
  • Remove npm dependencies (some of them not maintained anymore)

    • @adobe/node-fetch-retry
    • @amplitude/node
    • @keyv/redis
    • @oclif/command
    • @oclif/config
    • @oclif/errors
    • @salesforce/command
    • @salesforce/ts-types
    • find-package-json
    • node-fetch
  • Remove not used keyValueStores to keep only Salesforce one
"},{"location":"CHANGELOG/#4530-2024-08-20","title":"[4.53.0] 2024-08-20","text":"
  • Upgrade workflows to Node 20 (fixes https://github.com/hardisgroupcom/sfdx-hardis/issues/668)
  • Simplify login prompts messages (fixes https://github.com/hardisgroupcom/sfdx-hardis/issues/667)
  • Upgrade to MegaLinter v8 (own workflows + template workflows)
  • Update monitoring commands documentation
  • Upgrade npm dependencies
    • axios
    • inquirer
    • moment
    • open
    • ora
    • @supercharge/promise-pool
    • remove strip-ansi dependency to build local function
"},{"location":"CHANGELOG/#4520-2024-08-02","title":"[4.52.0] 2024-08-02","text":"
  • Minimum Node version is now 20
  • hardis:work:save : Improve performances when cleaning project files
  • Update Pipelines to add NOTIF_EMAIL_ADDRESS where it was missing
  • Remove MS_TEAMS_WEBHOOK_URL from all pipelines as MsTeamsProvider is deprecated (use EmailProvider instead)
  • Remove some useless code in EmailProvider
  • Replace glob-promise by glob package
"},{"location":"CHANGELOG/#4510-2024-08-01","title":"[4.51.0] 2024-08-01","text":"
  • Deprecate Microsoft Teams Web Hooks notifications
    • Must be replaced by Email Notifications using the Ms Teams Channel email.
  • Handle bug when a branch .sfdx-hardis.yml config file is empty
  • Upgrade default API version to 61
  • Additional log when generating manifest package.xml from org
  • Add error tip: Network issue (ECONNABORTED, ECONNRESET)
"},{"location":"CHANGELOG/#4501-2024-07-29","title":"[4.50.1] 2024-07-29","text":"
  • Fix report file name of hardis:org:monitor:limits
  • Fix crash when GitProvider has been wrongly configured, and display information message
"},{"location":"CHANGELOG/#4500-2024-07-29","title":"[4.50.0] 2024-07-29","text":"
  • Add message in case of deployment check passing thanks to testCoverageNotBlocking: true
  • hardis:org:diagnose:legacyapi : Fix display error declared in bug #652
  • Run legacy api detection daily with monitoring, as logs remain only 24h
"},{"location":"CHANGELOG/#4491-2024-07-27","title":"[4.49.1] 2024-07-27","text":"
  • Fix 4.49.0 (deployment error handler bug)
"},{"location":"CHANGELOG/#4490-2024-07-27","title":"[4.49.0] 2024-07-27","text":"
  • New command hardis:org:diagnose:instanceupgrade to get information about Org, its Salesforce instance and its next Platform Upgrade date. Sends notifications to Grafana if activated.
  • Refactor Monitoring checks documentation
  • hardis:project:deploy:sources:dx: After a failed Quick Deploy, use run with NoTestRun to improve perfs as we had previously succeeded to simulate the deployment
"},{"location":"CHANGELOG/#4481-2024-07-26","title":"[4.48.1] 2024-07-26","text":"
  • hardis:project:deploy:sources:dx: Fix issue with testCoverageNotBlocking
"},{"location":"CHANGELOG/#4480-2024-07-26","title":"[4.48.0] 2024-07-26","text":"
  • hardis:project:deploy:sources:dx: Allow new mode for running test during deployments: RunRepositoryTestsExceptSeeAllData (\u26a0\ufe0f Use with caution !)
"},{"location":"CHANGELOG/#4470-2024-07-22","title":"[4.47.0] 2024-07-22","text":"
  • Update emojis in prompts to make them more visible
  • Replace sfdx force:org:open by sf org open
"},{"location":"CHANGELOG/#4460-2024-07-18","title":"[4.46.0] 2024-07-18","text":"
  • Allow hardis:project:deploy:source:dx notifications to work if the deployment is performed before the Pull Request is merged (see Exotic Use Case)
    • Activate such mode with variable SFDX_HARDIS_DEPLOY_BEFORE_MERGE
  • Add link to Conga Article
  • Add Conga article in README list of articles
"},{"location":"CHANGELOG/#4450-2024-07-14","title":"[4.45.0] 2024-07-14","text":"
  • New command hardis:org:files:import to import files exported using hardis:org:files:export
  • Template management for SFDMU & files import/export
  • Update JSON schema to add v60 in autoCleanTypes
"},{"location":"CHANGELOG/#4443-2024-07-12","title":"[4.44.3] 2024-07-12","text":"
  • Set GITLAB_API_REJECT_UNAUTHORIZED=false to avoid SSH rejections from Gitlab API
"},{"location":"CHANGELOG/#4442-2024-07-09","title":"[4.44.2] 2024-07-09","text":"
  • New config skipCodeCoverage, to use only in branch scoped config to not check for code coverage (Use with caution because won't work when deploying to production !)
"},{"location":"CHANGELOG/#4441-2024-07-08","title":"[4.44.1] 2024-07-08","text":"
  • QuickFix testlevel default value
"},{"location":"CHANGELOG/#4440-2024-07-08","title":"[4.44.0] 2024-07-08","text":"
  • New JSON schema properties, to use ONLY on branch scoped config and with caution !
    • testLevel, to override the test level, with RunRepositoryTests for example
    • runtests, to override the list of tests to run, with ^(?!FLI|MyPrefix).* for example
    • testCoverageNotBlocking , to make code coverage not blocking on a branch
  • Take in account testCoverageNotBlocking in deployment checks and PR summaries
"},{"location":"CHANGELOG/#4430-2024-07-06","title":"[4.43.0] 2024-07-06","text":"
  • hardis:work:save : Update prompt messages
  • Remove direct URL to target org in case of deployment failure
  • AI Deployment Assistant: Fix identification of error messages
  • Add deployment tip \"Condition missing reference\"
"},{"location":"CHANGELOG/#4420-2024-07-02","title":"[4.42.0] 2024-07-02","text":"
  • hardis:project:deploy:sources:dx : If testlevel=RunRepositoryTests, option runtests can contain a regular expression to keep only class names matching it. If not set, it will run all test classes found in the repo
  • Reduce size of README
  • Update documentation about Authentication & Security
  • Add missing variables in workflows
"},{"location":"CHANGELOG/#4410-2024-06-29","title":"[4.41.0] 2024-06-29","text":"
  • AI Deployment Assistant: Integrate with OpenAI ChatGPT to find solutions to deployment issues
  • Monitoring: Default 120mn timeout in Azure Workflow
  • Backup: Replace colon in package file name
  • New command hardis:project:fix:profiletabs to add / hide tabs directly in XML when such info is not retrieved by Salesforce CLI
"},{"location":"CHANGELOG/#4402-2024-06-18","title":"[4.40.2] 2024-06-18","text":"
  • hardis:org:diagnose:audittrail: Define new not suspect actions
    • Currency
      • updateddatedexchrate
    • Custom App Licenses
      • addeduserpackagelicense
      • granteduserpackagelicense
    • Manage Users
      • unfrozeuser
    • Mobile Administration
      • assigneduserstomobileconfig
  • hardis:org:monitor:all: Define relevant items as weekly, not daily
"},{"location":"CHANGELOG/#4401-2024-06-17","title":"[4.40.1] 2024-06-17","text":"
  • hardis:project:clean:minimizeprofiles: Allow to skip profiles refactoring using .sfdx-hardis.yml property skipMinimizeProfiles (can be useful for Experience Cloud profiles)
"},{"location":"CHANGELOG/#4400-2024-06-13","title":"[4.40.0] 2024-06-13","text":"
  • Deployment tips: add missingDataCategoryGroup (no DataCategoryGroup named...)
  • handle commandsPreDeploy and commandPostDeploy to run custom command before and after deployments
    • If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

Example:

commandsPreDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='deploy.github@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\ncommandsPostDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='admin.user@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n
"},{"location":"CHANGELOG/#4390-2024-06-13","title":"[4.39.0] 2024-06-13","text":"
  • hardis:clean:references: new option v60
    • Remove v61 userPermissions that do not exist in v60
"},{"location":"CHANGELOG/#4382-2024-06-06","title":"[4.38.2] 2024-06-06","text":"
  • Fix npm packages installation for GitHub monitoring to avoid random failures
  • Add _notifKey in Grafana notifications to be able to build unique alerts
"},{"location":"CHANGELOG/#4381-2024-06-04","title":"[4.38.1] 2024-06-04","text":"
  • Add installed packages in monitoring backup logs
"},{"location":"CHANGELOG/#4380-2024-06-03","title":"[4.38.0] 2024-06-03","text":"
  • New command hardis:org:diagnose:licenses to send used licenses to monitoring logs like Grafana
  • hardis:org:diagnose:audittrail: Exclude some Add / Remove users from a Territory events from Suspect Audit Trail actions
  • hardis:org:diagnose:unusedusers: Fix metric name for ActiveUsers
"},{"location":"CHANGELOG/#4375-2024-05-31","title":"[4.37.5] 2024-05-31","text":"
  • hardis:org:purge:flow: Bulkify Flow deletion to improve performances
"},{"location":"CHANGELOG/#4374-2024-05-28","title":"[4.37.4] 2024-05-28","text":"
  • Fix pipeline and instructions for Monitoring using GitHub Actions
"},{"location":"CHANGELOG/#4373-2024-05-28","title":"[4.37.3] 2024-05-28","text":"
  • Revert to previous dashboards version to avoid issues with use of panel
  • Add debug capabilities for advanced cases (call with DEBUG=sfdxhardis)
"},{"location":"CHANGELOG/#4372-2024-05-27","title":"[4.37.2] 2024-05-27","text":"
  • Half-automate the retrieve of default Grafana Dashboards
  • Fix ticketing collection on PR with GitHub integration
  • Fix monitoring bitbucket pipeline so the git pull works
"},{"location":"CHANGELOG/#4371-2024-05-26","title":"[4.37.1] 2024-05-26","text":"
  • Truncate logs sent to Grafana Loki in case they are too big, to avoid they are not taken in account
    • Default truncate size: 500
  • Add flowPositions in .sfdx-hardis.yml JSON Schema
  • Add Grafana Cloud setup tutorial
"},{"location":"CHANGELOG/#4370-2024-05-21","title":"[4.37.0] 2024-05-21","text":"
  • New command hardis:project:clean:flowpositions to replace positions by 0 on AutoLayout Flows, in order to diminish conflicts
    • Can be automated at each hardis:work:save if flowPositions added in .sfdx-hardis.yml autoCleanTypes property
"},{"location":"CHANGELOG/#4360-2024-05-19","title":"[4.36.0] 2024-05-19","text":"
  • Update hardis:org:diagnose:unusedusers so it can also extract active users on a time period, thanks to option --returnactiveusers
  • Add ACTIVE_USERS in weekly monitoring jobs
  • Add JIRA variables to GitHub Workflows
"},{"location":"CHANGELOG/#4352-2024-05-15","title":"[4.35.2] 2024-05-15","text":"
  • Update monitoring default Gitlab, Azure & GitHub Workflows
"},{"location":"CHANGELOG/#4351-2024-05-14","title":"[4.35.1] 2024-05-14","text":"
  • Fix unused users notification identifier
"},{"location":"CHANGELOG/#4350-2024-05-14","title":"[4.35.0] 2024-05-14","text":"
  • New command sfdx hardis:org:diagnose:unusedusers to find users that don't use their license !
"},{"location":"CHANGELOG/#4341-2024-05-13","title":"[4.34.1] 2024-05-13","text":"
  • Notifications org identifier: replace dot by __ to avoid mess with Grafana label filters
"},{"location":"CHANGELOG/#4340-2024-05-12","title":"[4.34.0] 2024-05-12","text":"
  • NotifProvider
    • Updates to also send metrics to Prometheus
    • NOTIFICATIONS_DISABLE is now not applicable to ApiProvider who always sends notifs
"},{"location":"CHANGELOG/#4332-2024-05-06","title":"[4.33.2] 2024-05-06","text":"
  • hardis:org:test:apex : Always send coverageValue, coverageTarget and the list of failing classes to API logs
"},{"location":"CHANGELOG/#4331-2024-05-05","title":"[4.33.1] 2024-05-05","text":"
  • Api logs enhancements:
    • Add severity and severityIcon in all log elements details
    • Add dateTime property (ISO format) in all API logs
  • Remove deprecated way to call MsTeams notifications
  • hardis:org:monitor:limits : Fix bug when some values are not returned
"},{"location":"CHANGELOG/#4330-2024-05-04","title":"[4.33.0] 2024-05-04","text":"
  • New notifications provider: ApiProvider (beta), that allows to send notifications via HTTP/JSON to remote endpoints, like Grafana Loki, but also any custom one
  • New notification severity level: log, to send notifications via ApiProvider even when there is no detected issue
  • Update all existing notifications to add detailed log lines and additional log data
  • hardis:org:diagnose:audittrail: Fix lastndays not taken in account in some contexts
  • Complete refactoring of hardis:org:test:apex (same behavior but much organized code)
  • Notifications: Display success logs in blue
  • New monitoring command: sfdx hardis:org:monitor:limits to alert in case org limits are over 50% or 75% usage
  • Fix gitlab-ci-config.yml: More restrictive regex for deployment branches
"},{"location":"CHANGELOG/#4322-2024-05-01","title":"[4.32.2] 2024-05-01","text":"
  • Fix GitHub Actions check deploy workflow
"},{"location":"CHANGELOG/#4321-2024-04-30","title":"[4.32.1] 2024-04-30","text":"
  • hardis:work:new : Replace all non alphanumeric characters in new git branch name
"},{"location":"CHANGELOG/#4320-2024-04-24","title":"[4.32.0] 2024-04-24","text":"
  • Enhance BitBucket Integration, by @Alainbates in https://github.com/hardisgroupcom/sfdx-hardis/pull/584

    • Deployment status in Pull Request comments
    • Quick Deploy to enhance performance
  • Remove useless close WebSocket issue display
"},{"location":"CHANGELOG/#4312-2024-04-10","title":"[4.31.2] 2024-04-10","text":"
  • QuickFix Monitoring setup
"},{"location":"CHANGELOG/#4311-2024-04-10","title":"[4.31.1] 2024-04-10","text":"
  • Fix json output (remove other console logs that are not supposed to be here)
"},{"location":"CHANGELOG/#4310-2024-04-10","title":"[4.31.0] 2024-04-10","text":"
  • Add native Jenkins integration with Jenkinsfile for CI/CD Pipeline
  • Update default pipelines to add JIRA variables
  • Better handle of Jira API issues
"},{"location":"CHANGELOG/#4300-2024-04-02","title":"[4.30.0] 2024-04-02","text":"
  • Fix default package-no-overwrite.xml (typos on NamesCredential & RemoteSiteSetting)
  • Add links to FAQ in documentation
  • Add two new PMD rules for quality pmd-ruleset-high.xml and pmd-ruleset-medium.xml
"},{"location":"CHANGELOG/#4290-2024-03-25","title":"[4.29.0] 2024-03-25","text":"
  • Handle manifest/preDestructiveChanges.xml to delete items before deployments if necessary
  • Update documentation about integrations
  • Upgrade dependencies
"},{"location":"CHANGELOG/#4284-2024-03-11","title":"[4.28.4] 2024-03-11","text":"
  • Allow to override default scratch org duration using .sfdx-hardis.yml property scratchOrgDuration
"},{"location":"CHANGELOG/#4283-2024-03-05","title":"[4.28.3] 2024-03-05","text":"
  • Audit trail check: Ignore change phone number events
"},{"location":"CHANGELOG/#4282-2024-02-27","title":"[4.28.2] 2024-02-27","text":"
  • Fix wrong upgrade version notification
  • Update PMD bypassing rules doc
"},{"location":"CHANGELOG/#4281-2024-02-26","title":"[4.28.1] 2024-02-26","text":"
  • Fix issue when using email notifications with multiple recipients
"},{"location":"CHANGELOG/#4280-2024-02-21","title":"[4.28.0] 2024-02-21","text":"
  • Minimum Node.js version is now v18
  • New notifications channel: EmailProvider (use variable NOTIF_EMAIL_ADDRESS that can contain a comma-separated list of e-mail addresses)
  • Update existing call to notifications to add attached files when Email notif channel is active
  • Audit trail suspect actions: add the number of occurences for each suspect action found
  • Add more not suspect actions: dkimRotationPreparationSuccessful,createdReportJob,deletedReportJob,DeleteSandbox
  • Get tickets info: also check in ticket ids in branch name
  • Remove force config restDeploy=true
  • Rename Provided by sfdx-hardis into Powered by sfdx-hardis
"},{"location":"CHANGELOG/#4271-2024-02-10","title":"[4.27.1] 2024-02-10","text":"
  • Skip post-deployment notifications if nothing was deployed in delta mode
  • Simplify JIRA post deployment error output
"},{"location":"CHANGELOG/#4270-2024-02-09","title":"[4.27.0] 2024-02-09","text":"
  • Skip legacy notifications if NotifProvider has been used
  • Allow to send warning, error and critical notifications to secondary Slack or Teams channel, using variables SLACK_CHANNEL_ID_ERRORS_WARNINGS or MS_TEAMS_WEBHOOK_URL_ERRORS_WARNINGS
"},{"location":"CHANGELOG/#4263-2024-02-02","title":"[4.26.3] 2024-02-02","text":"
  • Add bash to sfdx-hardis docker image
"},{"location":"CHANGELOG/#4262-2024-02-01","title":"[4.26.2] 2024-02-01","text":"
  • Display warning message when failed to upload connected app
  • Update documentation about how to work on a dev sandbox / scratch org
"},{"location":"CHANGELOG/#4261-2024-01-31","title":"[4.26.1] 2024-01-31","text":"
  • Update Contributor User Guide
  • Empty predefined list of packages to install
"},{"location":"CHANGELOG/#4260-2024-01-27","title":"[4.26.0] 2024-01-27","text":"
  • Detect JIRA tickets even if there is only their identifiers in commits / PR text (see Documentation)
  • Fix PR comment ticket URL when detail has not been found on server
  • Monitoring: run non-critical commands only weekly by default (on saturdays)
"},{"location":"CHANGELOG/#4251-2024-01-18","title":"[4.25.1] 2024-01-18","text":"
  • Fix Microsoft Teams notifications formatting
"},{"location":"CHANGELOG/#4250-2024-01-15","title":"[4.25.0] 2024-01-15","text":"
  • Integration with Azure Boards (Work Items) ticketing system
    • Enrich MR/PR comments by adding work items references and links
    • Enrich notifications comments by adding work items references and links
    • Post a comment and a tag on Azure Work Items when they are deployed in a major org
  • Enhance JIRA integration by posting labels once an issue is deployed in a major org
"},{"location":"CHANGELOG/#4241-2024-01-11","title":"[4.24.1] 2024-01-11","text":"
  • Improve display of Microsoft Teams notifications
"},{"location":"CHANGELOG/#4240-2024-01-09","title":"[4.24.0] 2024-01-09","text":"
  • Add generic ticketing provider, that can identify any ticket references using:
    • GENERIC_TICKETING_PROVIDER_REGEX (Example for EasyVista: ([R|I][0-9]+-[0-9]+))
    • GENERIC_TICKETING_PROVIDER_URL_BUILDER (Example for EasyVista: https://instance.easyvista.com/index.php?ticket={REF})
"},{"location":"CHANGELOG/#4233-2023-12-28","title":"[4.23.3] 2023-12-28","text":"
  • hardis:org:purge:flow: Ignore managed flows - Fixes #532
  • hardis:work:new prevent parenthesis in branch name - Fixes #481
"},{"location":"CHANGELOG/#4232-2023-12-25","title":"[4.23.2] 2023-12-25","text":"
  • Catch errors when a JIRA comment has not been posted
  • Simplify package-no-overwrite.xml management logs
"},{"location":"CHANGELOG/#4231-2023-12-25","title":"[4.23.1] 2023-12-25","text":"
  • Handle case when tickets have no content
"},{"location":"CHANGELOG/#4230-2023-12-25","title":"[4.23.0] 2023-12-25","text":"
  • Use jira-client package instead of jira.js to be compliant not only with JIRA Cloud, but also with Jira on-premise
  • Improve delta logs
"},{"location":"CHANGELOG/#4220-2023-12-24","title":"[4.22.0] 2023-12-24","text":"
  • Add more info in pull requests comments
    • Commits summary
    • Jira tickets
    • Manual Actions
  • Integration with JIRA
    • Collect tickets info JIRA server
    • Post comment on tickets once they are deployed
"},{"location":"CHANGELOG/#4216-2023-12-22","title":"[4.21.6] 2023-12-22","text":"
  • New task: Ask confirmation before updating selected sandbox
  • Deployment tips
    • Visibility is not allowed for type
  • Audit trail, ignore more events
    • Holidays: holiday_insert
    • loginasgrantedtopartnerbt
"},{"location":"CHANGELOG/#4215-2023-12-14","title":"[4.21.5] 2023-12-14","text":"
  • hardis:org:diagnose:audittrail
    • Display user name in logs & notifications
    • Add new excluded actions: changedemail, changedsenderemail, queueMembership, enableSIQUserNonEAC
"},{"location":"CHANGELOG/#4214-2023-12-12","title":"[4.21.4] 2023-12-12","text":"
  • Fix the output column in the metadata status report to distinguish between inactive flows and validation rules identified in the source
"},{"location":"CHANGELOG/#4213-2023-12-08","title":"[4.21.3] 2023-12-08","text":"
  • Add more variables in default azure-pipelines.yml monitoring
  • Fix output file name of inactive metadatas audit
"},{"location":"CHANGELOG/#4212-2023-12-08","title":"[4.21.2] 2023-12-08","text":"
  • Downgrade base docker image to alpine:3.18
"},{"location":"CHANGELOG/#4211-2023-12-08","title":"[4.21.1] 2023-12-08","text":"
  • Update Azure Pipelines workflows to add more variables (+ error message giving this list of variables)
  • Fix notifs from Azure when spaces in url
  • Fix monitoring job on Azure
  • Add link to troubleshooting page if backup fails
  • Handle notification message when there is no apex in the project
  • Do not write report log when there are no differences during monitoring backup step
  • Do not try to post PR comments if not in check deploy job
  • Check unused licenses: fix crash when no permission set group assignments
  • Fix URL to Azure Pull Requests
  • Fix display name of PR author on Azure
"},{"location":"CHANGELOG/#4210-2023-12-06","title":"[4.21.0] 2023-12-06","text":"
  • hardis:lint:access: Add feature in access command to verify if an object permission exist twice or more in the same permission set
  • hardis:org:monitor:backup: Allow to exclude more metadata types using env variable MONITORING_BACKUP_SKIP_METADATA_TYPES (example: `MONITORING_BACKUP_SKIP_METADATA_TYPES=CustomLabel,StaticResource,Translation`)
  • When prompt for login, Suggest custom login URL as first choice by default
  • CICD: Update default gitlab-ci-config.yml
  • Configure Org CI Auth: Do not prevent to use main or master as production branch
"},{"location":"CHANGELOG/#4201-2023-12-04","title":"[4.20.1] 2023-12-04","text":"
  • Handle errors while calling monitoring commands
  • Increase jsforce Bulk API Timeout (60 seconds)
  • Set default Bulk Query retries to 3 attempts
"},{"location":"CHANGELOG/#4200-2023-12-04","title":"[4.20.0] 2023-12-04","text":"
  • Add feature in metadatastatus command to verify if a validation rule is inactive in the source
  • hardis:lint:metadatastatus
    • Check inactive validation rules
    • Add js documentation
  • Monitoring: Fix crash when a package name contains a slash
"},{"location":"CHANGELOG/#4191-2023-12-03","title":"[4.19.1] 2023-12-03","text":"
  • Output CSV mirror XLS files reports in a xls folder for easier browsing
  • hardis:org:diagnose:unusedlicenses
    • Add more Profile & Permission Set Licenses relationships
    • Handle special cases where license is not stored on the permission set, like Sales User !
"},{"location":"CHANGELOG/#4190-2023-12-02","title":"[4.19.0] 2023-12-02","text":"
  • New command sfdx hardis:org:diagnose:unusedlicenses to detect unused Permission Set Licenses (that you pay for anyway !)
"},{"location":"CHANGELOG/#4183-2023-11-29","title":"[4.18.3] 2023-11-29","text":"
  • Improve test cases notification
  • Enhance monitoring documentation with more descriptions and screenshots
"},{"location":"CHANGELOG/#4182-2023-11-29","title":"[4.18.2] 2023-11-29","text":"
  • hardis:work:save enhancements
    • Display more output during cleaning jobs
    • Keep userPermissions in Profiles when they are defined to false
"},{"location":"CHANGELOG/#4181-2023-11-29","title":"[4.18.1] 2023-11-29","text":"
  • Improve backup notifications display
"},{"location":"CHANGELOG/#4180-2023-11-29","title":"[4.18.0] 2023-11-29","text":"
  • Delta deployments is no more beta but Generally available
  • Org Monitoring is no more beta but Generally available
  • Generate CSV reports also in XSLX format for easier opening
"},{"location":"CHANGELOG/#4171-2023-11-28","title":"[4.17.1] 2023-11-28","text":"
  • Generate CSV output for hardis:org:monitor:backup
  • Refactor git detection of created/updated/deleted files
"},{"location":"CHANGELOG/#4170-2023-11-28","title":"[4.17.0] 2023-11-28","text":"
  • hardis:org:backup: Monitor installed packages
  • hardis:org:diagnose:audittrail: Add more ignored events
    • Email Administration: dkimRotationSuccessful
    • Manage Users: PermSetGroupAssign
    • Manage Users: PermSetGroupUnassign
  • Complete factorization of notification related methods
  • Do not remove applicationVisibilities and recordTypeVisibilities from Profiles if they are defined to false (allow to hide applications)
"},{"location":"CHANGELOG/#4161-2023-11-27","title":"[4.16.1] 2023-11-27","text":"
  • Core: Factorize CSV generation
"},{"location":"CHANGELOG/#4160-2023-11-27","title":"[4.16.0] 2023-11-27","text":"
  • Allow to run commands but disable notifications, using NOTIFICATIONS_DISABLE env var or notificationsDisable .sfdx-hardis.yml property.
  • Update JSON schema to add notificationsDisable and monitoringDisable properties
"},{"location":"CHANGELOG/#4151-2023-11-26","title":"[4.15.1] 2023-11-26","text":"
  • Improve notifs display with hardis:lint:access
"},{"location":"CHANGELOG/#4150-2023-11-24","title":"[4.15.0] 2023-11-24","text":"
  • Allow to disable not monitoring checks using monitoringDisable config file property, or MONITORING_DISABLE env var
  • Add new feature to identify custom fields without description
    • hardis:lint:missingattributes : New command to identify custom field without description
  • Add new feature to identify custom metadata (flows) inactive in project
    • hardis:lint:metadatastatus : New command to identify custom metadata (Labels and custom permissions) not used in source code
  • Rework generate csv file : generateReportPath and generateCsvFile
  • Update monitoring and slack documentation
  • Fix slack, teams & Azure notifications
"},{"location":"CHANGELOG/#4140-2023-11-23","title":"[4.14.0] 2023-11-23","text":"
  • Add new feature to identify custom metadata (Labels and custom permissions) not used in source code
  • hardis:lint:unusedmetadata : New command to identify custom metadata (Labels and custom permissions) not used in source code
  • Add two function getNotificationButtons and getBranchMarkdown in notifUtils.ts class to factorize code
  • Video explaining how to setup sfdx-hardis monitoring
  • Improve notifications display of lists
"},{"location":"CHANGELOG/#4134-2023-11-22","title":"[4.13.4] 2023-11-22","text":"
  • Upgrade ms-teams-webhook library so it works again !
  • hardis:org:diagnose:audittrail: Add changedmanager to not suspect setup actions
"},{"location":"CHANGELOG/#4132-2023-11-21","title":"[4.13.2] 2023-11-21","text":"
  • hardis:lint:access: Do not display empty metadata types in notification.
  • hardis:work:new: Improve prompt messages when asked if you want to refresh your sandbox
"},{"location":"CHANGELOG/#4131-2023-11-21","title":"[4.13.1] 2023-11-21","text":"
  • hardis:lint:access
    • Exclude custom settings, custom metadata and data cloud from fields access check
  • hardis:org:diagnose:audittrail
    • Add changedUserEmailVerifiedStatusUnverified and useremailchangesent to not suspect setup actions
  • Output info in case Ms Teams notification failed to be sent
"},{"location":"CHANGELOG/#4130-2023-11-19","title":"[4.13.0] 2023-11-19","text":"
  • Monitoring
    • Display package.xml content in logs when backup failed
    • Update default package-skip-items.xml
    • Call hardis:lint:access by default
    • Handle empty sections
  • hardis:org:diagnose:audittrail enhancements:
    • Add PerSetUnassign in not suspect monitored actions in Setup Audit Trail
    • Allow to append more allowed Setup Audit Trail sections & actions using .sfdx-hardis.yml property monitoringAllowedSectionsActions
  • hardis:lint:access enhancements:
    • Exclude required fields and MasterDetails, that can not be defined on Permission Sets
    • Output report file
    • Send slack notification
    • Add it by default in the monitoring commands
  • Doc
    • Update contributing infos (use sf plugins link)
  • hardis:files:export : Make the command compliant with Email attachments
"},{"location":"CHANGELOG/#4122-2023-11-15","title":"[4.12.2] 2023-11-15","text":"
  • Add user prompts for setup audit trail monitoring in interactive mode
"},{"location":"CHANGELOG/#4121-2023-11-15","title":"[4.12.1] 2023-11-15","text":"
  • Allow to exclude more usernames from monitoring using .sfdx-hardis.yml property monitoringExcludeUsernames
"},{"location":"CHANGELOG/#4120-2023-11-14","title":"[4.12.0] 2023-11-14","text":"
  • New command sfdx hardis:org:diagnose:audittrail to detect suspect actions in major orgs
    • Run by default in org monitoring
  • Fix notifications bulletpoints
  • Fix Gitlab provider token collections when in monitoring mode
"},{"location":"CHANGELOG/#4110-2023-11-14","title":"[4.11.0] 2023-11-14","text":"
  • If QuickDeploy failed, by default do not use delta for a deployment after a merge between a minor and a major branch
  • Allow to tweak delta deployments configuration (but it's really better to use default opinionated default config !)
"},{"location":"CHANGELOG/#4103-2023-11-12","title":"[4.10.3] 2023-11-12","text":"
  • Allow to configure monitoring on deployment repositories (Fix #477)
  • Forbid to configure CI authentication on main or master branch
  • Do not send legacy API notifications when there are no issues (Fix #478)
  • Upgrade dependencies
"},{"location":"CHANGELOG/#4102-2023-11-07","title":"[4.10.2] 2023-11-07","text":"
  • If you want to force the use full deployment on a delta project Pull Request/ Merge Request, add nodelta in your latest commit title or text.
  • Display FULL / DELTA / Quick Deploy info at the bottom of the logs.
  • sfdx hardis:org:retrieve:packageconfig: Do not replace Ids when updating the .sfdx-hardis.yml list of packages using packages listed from an org
"},{"location":"CHANGELOG/#4101-2023-11-06","title":"[4.10.1] 2023-11-06","text":"
  • Improve delta display in logs
  • Display Quick Deploy icon in slack notifications
  • Update Azure Pipelines default pipelines for delta deployments compliance
  • Update slack integration documentation
  • Add tutorials for authentication configuration on CI/CD servers
"},{"location":"CHANGELOG/#410o-2023-11-04","title":"[4.10.O] 2023-11-04","text":"
  • Allow to deploy in delta during PR checks between minor and major branches
    • To activate it, define useDeltaDeployment: true in .sfdx-hardis.yml, or set env variable USE_DELTA_DEPLOYMENT with value true
    • Make sure your GitHub, Gitlab, Azure or Bitbucket yaml workflows are up to date
  • Overwrite management: Rename packageDeployOnce.xml into package-no-overwrite.xml (compatibility with packageDeployOnce.xml file name is kept)
"},{"location":"CHANGELOG/#492-2023-10-31","title":"[4.9.2] 2023-10-31","text":"
  • Improve GitHub monitoring Workflow
  • Enhance monitoring documentation
"},{"location":"CHANGELOG/#491-2023-10-31","title":"[4.9.1] 2023-10-31","text":"
  • New deployment error tips:
    • Invalid custom summary formula definition
  • Add artifacts config on bitbucket-pipelines.yml
  • Add more comments in Monitoring workflows
"},{"location":"CHANGELOG/#490-2023-10-30","title":"[4.9.0] 2023-10-30","text":"
  • Refactor Monitoring configuration and execution (beta)
    • If you already have a monitoring v1 repository, deprecate it and create a new one with the new monitoring setup and pipelines
    • Send slack notifications
      • Latest updates detected in org
      • Failing apex tests, or insufficient code coverage
      • Deprecated API calls detected
    • Full setup documentation
      • GitHub Actions
      • Gitlab CI
      • Azure Pipelines
      • Bitbucket Pipelines
    • Totally rewritten command sfdx hardis:org:configure:monitoring
    • New command sfdx hardis:org:monitor:backup
    • New command sfdx hardis:org:monitor:all
  • Simplify sfdx hardis:project:configure:auth (Configure Org CI Authentication)
  • Disable auto-update for .gitignore & .forceignore
  • Improve documentation related to pull and commit
"},{"location":"CHANGELOG/#481-2023-10-28","title":"[4.8.1] 2023-10-28","text":"
  • Catch \"Cannot start the OAuth redirect server on port 1717\" and give instructions to user to kill the process
"},{"location":"CHANGELOG/#480-2023-10-25","title":"[4.8.0] 2023-10-25","text":"
  • Allow to use Device login for Code Builder compatibility
  • New option to clear cache if an authenticated org does not appear in the choices
"},{"location":"CHANGELOG/#470-2023-10-24","title":"[4.7.0] 2023-10-24","text":"
  • hardis:org:files:export: New configuration available to export files: outputFileNameFormat, with available values:
    • title (default)
    • title_id
    • id_title
    • id
"},{"location":"CHANGELOG/#466-2023-10-20","title":"[4.6.6] 2023-10-20","text":"
  • Fix crash when converting orgCoverage to string
"},{"location":"CHANGELOG/#465-2023-10-17","title":"[4.6.5] 2023-10-17","text":"
  • Do not use direct call to jsforce dependency to avoid crash ! ( related to https://github.com/forcedotcom/cli/issues/2508#issuecomment-1760274510 )
  • Update documentation
  • Update comparative table in doc
"},{"location":"CHANGELOG/#464-2023-09-28","title":"[4.6.4] 2023-09-28","text":"
  • hardis:work:save : Fix issue when there is an empty commit because of pre-commit hooks
"},{"location":"CHANGELOG/#463-2023-09-27","title":"[4.6.3] 2023-09-27","text":"
  • Add installation video tutorial: https://www.youtube.com/watch?v=LA8m-t7CjHA
"},{"location":"CHANGELOG/#462-2023-09-26","title":"[4.6.2] 2023-09-26","text":"
  • Fix return code for wrapper commands force:source:deploy, force:source:push and force:mdapi:deploy
  • Fix --skipauth not taken in account with @salesforce/cli
  • Fixed PR coverage to use float over string
"},{"location":"CHANGELOG/#461-2023-09-26","title":"[4.6.1] 2023-09-26","text":"
  • Fix auth issue with force:source & force:mdapi wrapper sfdx-hardis commands
"},{"location":"CHANGELOG/#460-2023-09-20","title":"[4.6.0] 2023-09-20","text":"
  • sfdx-hardis & Slack Integration

    • Easy configuration
    • Deployment notifications to a common channel, and also to git branch dedicated channel
  • Native BitBucket CI/CD Pipeline for PR deployment checks and deployments to major orgs after merge

    • PR comments are not implemented yet but BitBucket can already be used for production
  • hardis:project:deploy:dx enhancements:

    • Added new option --testlevel RunRepositoryTests which will dynamically detect all GIT repository test classes and runs the deployment with found tests. This will speed up the validation/deployment on cases where GIT repository module contains subset of all tests found in the org
    • Added --runtests support in order to pass certain APEX test classes when --testlevel RunSpecifiedTests is used
  • Embed Dreamforce 23 slides in documentation
"},{"location":"CHANGELOG/#451-2023-09-11","title":"[4.5.1] 2023-09-11","text":"
  • GitHub Integration: Fix Quick Deploy on Pull Requests
"},{"location":"CHANGELOG/#450-2023-09-11","title":"[4.5.0] 2023-09-11","text":"
  • GitHub Integration: Implement automated comments & Quick Deploy on Pull Requests
"},{"location":"CHANGELOG/#440-2023-09-10","title":"[4.4.0] 2023-09-10","text":"
  • Make sfdx-hardis CI/CD Pipelines natively compliant with GitHub Actions , by @legetz
  • Create sfdx project: Change defaut first major branch name to integration (it was previously develop)
  • Update default API version to 58.0
  • Fix bug when user email is input the first time
"},{"location":"CHANGELOG/#432-2023-09-08","title":"[4.3.2] 2023-09-08","text":"
  • Updates new task, commit & save task documentation & screenshots
"},{"location":"CHANGELOG/#431-2023-09-07","title":"[4.3.1] 2023-09-07","text":"
  • Improve message when deploying metadata to org from local sfdx-hardis
  • Improve documentation to handle merge requests and display links at the end of hardis:work:save
"},{"location":"CHANGELOG/#430-2023-09-05","title":"[4.3.0] 2023-09-05","text":"
  • Back to normal since https://github.com/forcedotcom/cli/issues/2445 is fixed
"},{"location":"CHANGELOG/#425-2023-09-05","title":"[4.2.5] 2023-09-05","text":"
  • Downgrade to sfdx-cli until https://github.com/forcedotcom/cli/issues/2445 is solved.
"},{"location":"CHANGELOG/#424-2023-09-05","title":"[4.2.4] 2023-09-05","text":"
  • Downgrade @salesforce/plugin-deploy-retrieve to v1.17.6 as workaround for SF cli bug https://github.com/forcedotcom/cli/issues/2445
"},{"location":"CHANGELOG/#423-2023-09-04","title":"[4.2.3] 2023-09-04","text":"
  • Fix issues with Org monitoring when there are issues with Legacy API
"},{"location":"CHANGELOG/#422-2023-09-01","title":"[4.2.2] 2023-09-01","text":"
  • Fix upgrade warning message that should not appear when there is no upgrade to perform (detected by @mamasse19)
"},{"location":"CHANGELOG/#421-2023-08-30","title":"[4.2.1] 2023-08-30","text":"
  • Fix issue in sfdx commands wrapping following the use of @salesforce/cli
  • Config auth: phrases in bold when needing to relaunch the same command after org selection
"},{"location":"CHANGELOG/#420-2023-08-30","title":"[4.2.0] 2023-08-30","text":"
  • Simplify UX of hardis:project:configure:auth
  • Factorize prompting of email
  • Expire sfdx-hardis connected app token after 3h
  • Update documentation to add workaround in case there is a crash when retrieving all sources when initializing a DX project from an existing org
  • Add output to explain how to not use QuickDeploy if not wanted
  • Update Quick Deploy documentation
"},{"location":"CHANGELOG/#412-2023-08-24","title":"[4.1.2] 2023-08-24","text":"
  • When there is a crash in forceinstalled:list , do not crash but return empty array and display an error message
"},{"location":"CHANGELOG/#411-2023-08-23","title":"[4.1.1] 2023-08-23","text":"
  • Improve error message when Git Provider not available
  • Update default azure-pipelines-deployment.yml to add mandatory variables for QuickDeploy
SYSTEM_ACCESSTOKEN: $(System.AccessToken)\nCI_SFDX_HARDIS_AZURE_TOKEN: $(System.AccessToken)\nSYSTEM_COLLECTIONURI: $(System.CollectionUri)\nBUILD_REPOSITORY_ID: $(Build.Repository.ID)\n
"},{"location":"CHANGELOG/#410-2023-08-22","title":"[4.1.0] 2023-08-22","text":"
  • Manage QuickDeploy when available (disable by defining env var SFDX_HARDIS_QUICK_DEPLOY=false)
"},{"location":"CHANGELOG/#401-2023-08-18","title":"[4.0.1] 2023-08-18","text":"

BREAKING CHANGE: If you are not using sfdx-hardis docker images, you need to manually update your CI/CD pipelines scripts using sfdx-hardis (gitlab-ci.yml, azure-pipelines.yml...) to:

  • replace sfdx-cli by @salesforce/cli
  • Add sf plugins install @salesforce/plugin-packaging just after npm install @salesforce/cli --global

Other upgrades

  • Upgrade CI/CD scripts and sfdx-hardis docker images from sfdx-cli to @salesforce/cli (sfdx commands remain called in background), and add @salesforce/plugin-packaging by default
  • Now also release sfdx-hardis images on GitHub Packages (ghcr.io)
  • Internal CI refactorization
    • Secure releases with GitHub Actions permissions & environments
    • Switch to official docker build & push action
    • Upgrade MegaLinter
    • Upgrade npm dependencies
"},{"location":"CHANGELOG/#3194-2023-07-18","title":"[3.19.4] 2023-07-18","text":"
  • Add confirmation before resetting a git branch from VsCode command \"Reset selected list of items to merge\" (from an original idea of @derroman)
"},{"location":"CHANGELOG/#3193-2023-07-10","title":"[3.19.3] 2023-07-10","text":"
  • Allow to disable red colors for force:source:deploy output using env variable SFDX_HARDIS_DEPLOY_ERR_COLORS=false
"},{"location":"CHANGELOG/#3192-2023-07-06","title":"[3.19.2] 2023-07-06","text":"
  • Add packaging in online doc menu
"},{"location":"CHANGELOG/#3191-2023-07-05","title":"[3.19.1] 2023-07-05","text":"
  • Add Hotfix management (BUILD vs RUN) in CI/CD documentation
  • Add Packaging & package version instructions in documentation
"},{"location":"CHANGELOG/#3190-2023-07-03","title":"[3.19.0] 2023-07-03","text":"
  • Monitoring: Do not exclude custom fields on managed objects -ex: Remove Ns__Object__c.Ns__Field__c, but keep Ns__Object__c.Field__c
"},{"location":"CHANGELOG/#3181-2023-06-13","title":"[3.18.1] 2023-06-13","text":"
  • QuickFix hardis:work:save when branch has not been created on the computer
"},{"location":"CHANGELOG/#3180-2023-06-07","title":"[3.18.0] 2023-06-07","text":"
  • Clean entitlement items, by @yamioliva in https://github.com/hardisgroupcom/sfdx-hardis/pull/381
"},{"location":"CHANGELOG/#3170-2022-05-30","title":"[3.17.0] 2022-05-30","text":"
  • New command hardis:org:generate:packagexmlfull to generate the full package.xml of a selected Salesforce org
"},{"location":"CHANGELOG/#3161-2022-05-29","title":"[3.16.1] 2022-05-29","text":"
  • Also remove standard fields when running hardis:project:clean:standarditems
  • New Deployment tips
    • Wrong api Version of a Metadata
    • Unknown user
  • Upgrade to MegaLinter v7
"},{"location":"CHANGELOG/#3160-2022-05-24","title":"[3.16.0] 2022-05-24","text":"
  • New ENV variables to override default wait on retrieve/deploy/test commands
    • SFDX_RETRIEVE_WAIT_MINUTES
    • SFDX_DEPLOY_WAIT_MINUTES
    • SFDX_TEST_WAIT_MINUTES
  • Update default .forceignore content
"},{"location":"CHANGELOG/#3150-2022-05-11","title":"[3.15.0] 2022-05-11","text":"
  • Allow to define property availableProjects so when user clicks on New task (hardis:work:new), he/she is asked to select a project, that will be used to build the new git branch name
  • When creating new task, store the target branch so it is not prompted again when waiting to save/publish the task.
"},{"location":"CHANGELOG/#3142-2022-05-03","title":"[3.14.2] 2022-05-03","text":"
  • More explicit text to ask user if he/she wants to update its selected sandbox while creating a new task
  • Do not ask to change default target branch if there are multiple available branches
"},{"location":"CHANGELOG/#3141-2022-04-19","title":"[3.14.1] 2022-04-19","text":"
  • Allow to override the default deployment wait time (60) using variable SFDX_DEPLOY_WAIT_MINUTES
  • Update JSON schema to add customOrgColors
"},{"location":"CHANGELOG/#3140-2022-04-14","title":"[3.14.0] 2022-04-14","text":"
  • Fix breaking change of sfdx-git-delta (many thanks @scolladon !)
  • Deploy tips
    • Invalid report type
    • Missing report
    • Update missing email template message
  • Add more space between error lines in PR/MR comments
  • Upgrade xml2js dependency
  • Update call to MegaLinter in Azure integrations
"},{"location":"CHANGELOG/#3131-2022-04-12","title":"[3.13.1] 2022-04-12","text":"
  • Fix missing sfdx-git-delta in Docker image
"},{"location":"CHANGELOG/#3130-2022-04-06","title":"[3.13.0] 2022-04-06","text":"
  • Change defaut package install mode to AdminsOnly
  • When minimizing Profiles, do not remove the personAccountDefault=true elements
  • Add new deploy tip: Error parsing file
"},{"location":"CHANGELOG/#3123-2022-04-04","title":"[3.12.3] 2022-04-04","text":"
  • Do not add EmailTemplate and Flows as separate items in deploymentPlan, as metadata API now can handle their deployment with the rest of the sources
  • Add new deployTip: Missing multi-currency field
  • Update label when creating a new task using an existing sandbox
"},{"location":"CHANGELOG/#3122-2022-03-30","title":"[3.12.2] 2022-03-30","text":"
  • New deployment error tips
    • SortOrder must be in sequential order from 1. (Duplicate Rules issue)
    • Invalid field:ACCOUNT.NAME in related list:RelatedContactAccountRelationList
  • Add more matchers for duplicate detector
"},{"location":"CHANGELOG/#3121-2022-03-29","title":"[3.12.1] 2022-03-29","text":"
  • Fix false positive error in deployment job when there is no related Pull/Merge request
"},{"location":"CHANGELOG/#3120-2022-03-23","title":"[3.12.0] 2022-03-23","text":"
  • Integration with Azure Pipelines Pull Request threads
  • hardis:work:new: Allow to select no org even of sandbox or scratch is forced on the project using config property allowedOrgTypes
  • Doc: rename User Guide into Contributor Guide
"},{"location":"CHANGELOG/#3111-2022-03-20","title":"[3.11.1] 2022-03-20","text":"
  • Better fix for root path issues (internal error)
"},{"location":"CHANGELOG/#3110-2022-03-20","title":"[3.11.0] 2022-03-20","text":"
  • Fix root path issues (internal error)
"},{"location":"CHANGELOG/#3102-2022-03-16","title":"[3.10.2] 2022-03-16","text":"
  • Fix sandbox check when calling hardis:source:push
"},{"location":"CHANGELOG/#3101-2022-03-15","title":"[3.10.1] 2022-03-15","text":"
  • Quick fix Gitlab integration when there is no MR associated to a deployment
"},{"location":"CHANGELOG/#3100-2022-03-15","title":"[3.10.0] 2022-03-15","text":"
  • Post a Gitlab Merge Request note when checking a deployment (beta)
    • Deployment errors with resolution tips
    • Failing test classes
    • Code coverage
  • Do not remove then restore lookup filters when source:push on a source-tracked sandbox
  • Catch and display errors when caused by internet connection issue
"},{"location":"CHANGELOG/#392-2022-03-09","title":"[3.9.2] 2022-03-09","text":"
  • Update deploy tips for error Unknown user permission: SendExternalEmailAvailable
"},{"location":"CHANGELOG/#391-2022-03-08","title":"[3.9.1] 2022-03-08","text":"
  • Improve logs for false positive after package installation failure
  • Remove useless and scary log after a successful login :)
  • Remove npm cache from Docker image
"},{"location":"CHANGELOG/#390-2022-03-08","title":"[3.9.0] 2022-03-08","text":"
  • New task with source tracked sandbox:
    • Do not allow to select a major org for dev or config
    • Open SF org if selected from the already connected list
    • Init packages only if defined in config
    • Enhance labels
  • Save task: Notify that once the merge request is merged, you must create a new task that will create a new branch
  • Improve login error messages
  • Use latest version of MegaLinter
"},{"location":"CHANGELOG/#380-2022-03-03","title":"[3.8.0] 2022-03-03","text":"
  • Manage deprecation of force:mdapi:legacy:deploy, replaced by force:mdapi:deploy
  • Update default packageDeployOnce.xml when creating a new project (related to Overwrite management)
  • Update CI/CD documentation
    • Initialize orgs
  • Update labels of prompts when creating a new sfdx-hardis project
"},{"location":"CHANGELOG/#371-2022-02-27","title":"[3.7.1] 2022-02-27","text":"
  • Use tooling API to retrieve ApexLogs for deletion, by @thvd in https://github.com/hardisgroupcom/sfdx-hardis/pull/321
"},{"location":"CHANGELOG/#370-2022-02-27","title":"[3.7.0] 2022-02-27","text":"
  • Add demo video about configuring authentication between CI and Salesforce orgs
  • Update CI/CD documentation
  • Update branding
"},{"location":"CHANGELOG/#360-2022-02-23","title":"[3.6.0] 2022-02-23","text":"
  • Add sfdx sources to monitoring for better readability
  • Change example of email addresses for prompts
  • Update CI/CD recommendations in documentation
"},{"location":"CHANGELOG/#350-2022-02-22","title":"[3.5.0] 2022-02-22","text":"
  • Update default overwrite config (packageDeployOnce.xml)
  • Setup CI: Define default Azure pipelines YML files
  • Fix notification logs for Azure Pipelines
"},{"location":"CHANGELOG/#340-2022-02-21","title":"[3.4.0] 2022-02-21","text":"
  • Move documentation to https://sfdx-hardis.cloudity.com
"},{"location":"CHANGELOG/#332-2022-02-17","title":"[3.3.2] 2022-02-17","text":"
  • Fix default monitoring for Azure pipelines
  • Update CI documentation (Azure)
"},{"location":"CHANGELOG/#331-2022-02-16","title":"[3.3.1] 2022-02-16","text":"
  • Fix check of newer package installed
"},{"location":"CHANGELOG/#330-2022-02-14","title":"[3.3.0] 2022-02-14","text":"
  • Compliance of monitoring setup with Azure Pipelines
  • hardis:org:retrieve:source:metadata enhancements
    • new option --includemanaged, disabled by default, to avoid having too many items to retrieve during monitoring job
    • allow to force monitoring additional tasks using env var SFDX_HARDIS_MONITORING set to \"true\"
"},{"location":"CHANGELOG/#320-2022-02-10","title":"[3.2.0] 2022-02-10","text":"
  • Fix issue when logging to a new org during command hardis:source:retrieve
  • Implement check of code coverage when calling sfdx hardis:project:deploy:sources:dx --check
    • 75% minimum by default, overridable in property apexTestsMinCoverageOrgWide in .sfdx-hardis.yml, or using env var APEX_TESTS_MIN_COVERAGE_ORG_WIDE
  • Add --checkcoverage option to wrapper command hardis:source:deploy
    • Example: sfdx hardis:source:deploy -x manifest/package.xml --wait 60 --ignorewarnings --testlevel RunLocalTests --postdestructivechanges ./manifest/destructiveChanges.xml --targetusername nicolas.vuillamy@cloudity.com --checkonly --checkcoverage --verbose --coverageformatters json-summary
"},{"location":"CHANGELOG/#310-2022-02-07","title":"[3.1.0] 2022-02-07","text":"
  • Reset local sfdx tracking when reusing a sandbox for a new task
"},{"location":"CHANGELOG/#300-2022-02-07","title":"[3.0.0] 2022-02-07","text":"
  • Breaking change: SFDX_HARDIS_DEPLOY_IGNORE_SPLIT_PACKAGES is now \"true\" by default. If you want to apply the deploymentPlan in .sfdx-hardis, you need to define variable SFDX_HARDIS_DEPLOY_IGNORE_SPLIT_PACKAGES=\"false\"
"},{"location":"CHANGELOG/#21000-2022-02-07","title":"[2.100.0] 2022-02-07","text":"
  • hardis:work:new:: When creating a new task and using a source-tracked sandbox, ask user to push sources, assign permission sets and load data to initialize it.
  • Add explicit error message when scratch org creation is caused by a limit reach
  • Update default API version to 56.0
  • Improve labels when prompting to select an org
  • Update CI/CD documentation
"},{"location":"CHANGELOG/#2991-2022-01-31","title":"[2.99.1] 2022-01-31","text":"
  • Fix hardis:project:clean:hiddenitems when multiple files in the same folder match the same glob pattern
  • Update documentation, fix typos and dead links
"},{"location":"CHANGELOG/#2990-2022-01-30","title":"[2.99.0] 2022-01-30","text":"
  • Replace prompts library by inquirer, because prompts is buggy
  • Dockerfile: Workaround for https://github.com/forcedotcom/salesforcedx-apex/issues/213 (force:apex:test:run with code coverage crashing on some Gitlab runners with Invalid time value)
  • Allow to override the proposed branch names when calling hardis:work:new, using property branchPrefixChoices
  • hardis:project:clean:hiddenitems: Also clean LWC with hidden content
  • Add yarn in dockerfile
"},{"location":"CHANGELOG/#2981-2022-01-23","title":"[2.98.1] 2022-01-23","text":"
  • Fix hardis:org:purge:flow when flow prompt selection is all
"},{"location":"CHANGELOG/#2980-2022-01-23","title":"[2.98.0] 2022-01-23","text":"
  • Documentation: Add CI/CD user guide and release manager guide, available at https://sfdx-hardis.cloudity.com/salesforce-ci-cd-home/
  • New .sfdx-hardis.yml config property allowedOrgTypes, allowing to define the type(s) or org that can be used for implementation: (sandbox and/or scratch)
"},{"location":"CHANGELOG/#2973-2022-11-30","title":"[2.97.3] 2022-11-30","text":"
  • QuickFix System.debug removal
"},{"location":"CHANGELOG/#2972-2022-11-30","title":"[2.97.2] 2022-11-30","text":"
  • QuickFix
"},{"location":"CHANGELOG/#2971-2022-11-30","title":"[2.97.1] 2022-11-30","text":"
  • QuickFix hardis:lint:access
"},{"location":"CHANGELOG/#2970-2022-11-30","title":"[2.97.0] 2022-11-30","text":"
  • New command hardis:lint:access to analyze of items in sources are not present within profiles and/or permission sets
"},{"location":"CHANGELOG/#2961-2022-11-17","title":"[2.96.1] 2022-11-17","text":"
  • Fix error when assigning already existing PS
  • Update default CI config
"},{"location":"CHANGELOG/#2960-2022-11-09","title":"[2.96.0] 2022-11-09","text":"
  • Replace sfdx force:package:install with sfdx force:package:beta:install
  • Do not cause deployment to fail when a deploying an older managed package version
    • Instead, deployment will assume the newer version meets the requirement
  • hardis:scratch:create : Avoid error in case of already existing assignment of PermissionSet SfdxHardisDeferSharingRecalc
  • Update Node.js minimum version to 16.x
"},{"location":"CHANGELOG/#2952-2022-10-19","title":"[2.95.2] 2022-10-19","text":"
  • Replace use of sfpowerkit by default command sfdx force:source:manifest:create
  • Manage cache for listing orgs
  • Update hardisversion:create to allow to
    • install it later on an org
    • immediately delete it
  • New command hardis:project:metadata:findduplicates to detect when git messed during an automated merging of conflicts
  • Factorize check of sfdx project existence
  • Fix default gitlab-ci default pipeline
  • Replace supportsDevhubUsername by requiresDevhubUsername in command classes when necessary
  • Add parameters skipauth and websocket on sfdx hardis:project:metadata:duplicate
  • Add missing parameter skipauth on sfdx hardis:package:install
"},{"location":"CHANGELOG/#2943-2022-09-15","title":"[2.94.3] 2022-09-15","text":"
  • Automate SSL certificate generation + force:source:deploy replaced by force:source:legacy:deploy
"},{"location":"CHANGELOG/#2942-2022-09-09","title":"[2.94.2] 2022-09-09","text":"
  • hardis:project:clean:minimizeprofiles: Do not strip tabVisibilities from Profiles
"},{"location":"CHANGELOG/#2941-2022-09-01","title":"[2.94.1] 2022-09-01","text":"
  • Lock sfpowerkit dependency to 4.2.13 to avoid error caused by deprecation of sfpowerkit:org:build:manifest
"},{"location":"CHANGELOG/#2940-2022-08-31","title":"[2.94.0] 2022-08-31","text":"
  • Update documentation to initialize scratch org
  • Update JSON schema to add scratchOrgInitApexScripts
  • Fix execution of scripts defined in scratchOrgInitApexScripts
"},{"location":"CHANGELOG/#2930-2022-08-02","title":"[2.93.0] 2022-08-02","text":"
  • Fix handling of new sfdx error format so we can again identify deployment tips
  • New deployment tips:
    • Cannot update a field to a Summary from something else
"},{"location":"CHANGELOG/#2920-2022-07-29","title":"[2.92.0] 2022-07-29","text":"
  • New command hardis:org:retrieve:source:analytics to retrieve all analytics (CRM Analytics/TCRM) sources
  • New deployment tips (Wave analytics)
  • Fix writePackageXml method when there is not an existing file
"},{"location":"CHANGELOG/#2910-2022-07-15","title":"[2.91.0] 2022-07-15","text":"
  • Fix issue when force:source command wrappers arguments contain spaces (#269))
  • Upgrade MegaLinter to v6
  • Upgrade yarn dependencies
"},{"location":"CHANGELOG/#2900-2022-06-24","title":"[2.90.0] 2022-06-24","text":"
  • Events to open generated files when called from VsCode SFDX Hardis
  • New deployTips
"},{"location":"CHANGELOG/#2893-2022-06-21","title":"[2.89.3] 2022-06-21","text":"
  • Fix exported file extension (#266)
"},{"location":"CHANGELOG/#2892-2022-06-17","title":"[2.89.2] 2022-06-17","text":"
  • Build full manifest using sfpowerkit excluding ManagedContentTypeBundle because it is not managed by retrieve
"},{"location":"CHANGELOG/#2891-2022-06-16","title":"[2.89.1] 2022-06-16","text":"
  • Auto-update gitlab-ci.yml only if variable AUTO_UPDATE_GITLAB_CI_YML is set
"},{"location":"CHANGELOG/#2890-2022-06-12","title":"[2.89.0] 2022-06-12","text":"
  • hardismergexml: New command to merge package.Xml files
"},{"location":"CHANGELOG/#2880-2022-06-11","title":"[2.88.0] 2022-06-11","text":"
  • hardis:project:clean:systemdebug: New command to comment or remove all System.debug from apex and triggers
"},{"location":"CHANGELOG/#2875-2022-05-18","title":"[2.87.5] 2022-05-18","text":"
  • toml2csv: Allow hardcoded values for concat
  • Refactor internal CI to use 7.148.3 as recommended version
"},{"location":"CHANGELOG/#2874-2022-05-18","title":"[2.87.4] 2022-05-18","text":"
  • Fix configure org CI
  • Hide auth info from console logs
  • Fix Bulk Update job not closed
"},{"location":"CHANGELOG/#2873-2022-05-12","title":"[2.87.3] 2022-05-12","text":"
  • Auto-update .gitlab-ci.yml if a newest version exists
"},{"location":"CHANGELOG/#2872-2022-05-11","title":"[2.87.2] 2022-05-11","text":"
  • Refactor report directory management
"},{"location":"CHANGELOG/#2871-2022-05-11","title":"[2.87.1] 2022-05-11","text":"
  • Fix monitoring default pipeline
"},{"location":"CHANGELOG/#2870-2022-05-08","title":"[2.87.0] 2022-05-08","text":"
  • New command hardis:project:clean:xml allowing to automate the manual cleaning in the XML files using glob pattern and xPath
  • Reorganize work:save command code + add auto mode
  • Call Save command from Retrofit command to update package.xml files and make sure sources have been cleaned
"},{"location":"CHANGELOG/#2861-2022-05-06","title":"[2.86.1] 2022-05-06","text":"
  • hardis:work:new : Propose to reuse current scratch org when it is not in the local list
  • hardis:work:save : Propose to push git branch on server when it is still untracked
"},{"location":"CHANGELOG/#2860-2022-05-03","title":"[2.86.0] 2022-05-03","text":"
  • New wrapper command: sfdx hardis:source:retrieve
  • Quickfix toml2csv
"},{"location":"CHANGELOG/#2852-2022-05-02","title":"[2.85.2] 2022-05-02","text":"
  • Fix toml2csv error log
  • Deployment tips
    • Allow deployment with pending Apex Jobs
    • Update Can not find folder
"},{"location":"CHANGELOG/#2851-2022-04-27","title":"[2.85.1] 2022-04-27","text":"
  • Enhance sfdx hardis:org:retrieve:sources:retrofit command + JSON schema updates
"},{"location":"CHANGELOG/#2850-2022-04-27","title":"[2.85.0] 2022-04-27","text":"
  • Enhance sfdx hardis:org:retrieve:sources:retrofit command
  • Ad deployment tip: Invalid field in related list
"},{"location":"CHANGELOG/#2840-2022-04-27","title":"[2.84.0] 2022-04-27","text":"
  • Update deployTips: improve unknown custom field message
  • New command sfdx hardis:doc:extract:permsetgroups to generate permission set groups documentation
"},{"location":"CHANGELOG/#2836-2022-04-26","title":"[2.83.6] 2022-04-26","text":"
  • Fix hardis:work:save who sometimes forgot to ask to push commits
"},{"location":"CHANGELOG/#2835-2022-04-24","title":"[2.83.5] 2022-04-24","text":"
  • Update deployment tips
"},{"location":"CHANGELOG/#2830-2022-04-20","title":"[2.83.0] 2022-04-20","text":"
  • New deployment tips:
    • Not valid sharing model
  • Improve purge flows for manual users
  • Improve badwords detector
  • Open scratch org when reusing one
  • Hide prompt result when it contains sensitive information
"},{"location":"CHANGELOG/#2822-2022-04-19","title":"[2.82.2] 2022-04-19","text":"
  • New deployTip: Can not change type due to existing data
  • Do not replace ListView Everything by Mine when we are just simulating deployment
"},{"location":"CHANGELOG/#2821-2022-04-16","title":"[2.82.1] 2022-04-16","text":"
  • QuickFix platform compatibility for sfdx hardis:org:fix:listviewmine
"},{"location":"CHANGELOG/#2820-2022-04-16","title":"[2.82.0] 2022-04-16","text":"
  • New command sfdx hardis:org:fix:listviewmine as a workaround to force:source:deploy not allowing ListView with scope Mine
"},{"location":"CHANGELOG/#2810-2022-04-15","title":"[2.81.0] 2022-04-15","text":"
  • New property autoRetrieveWhenPull to always retrieve some sources when calling hardis:source:pull (useful when sfdx tracking forgets some updates)
"},{"location":"CHANGELOG/#2800-2022-04-15","title":"[2.80.0] 2022-04-15","text":"
  • Simplify and document more hardis:work:new , hardis:work:pull and hardis:work:save
  • Open org in browser when fetched from scratch org pool
  • More deploymentTips
  • Add customPlugins definition in json schema
"},{"location":"CHANGELOG/#2790-2022-04-10","title":"[2.79.0] 2022-04-10","text":"
  • New property extends in .sfdx-hardis.yml, to allow local config file to extend from remote file
  • Add customCommands definition in json schema
"},{"location":"CHANGELOG/#2784-2022-04-09","title":"[2.78.4] 2022-04-09","text":"
  • Update documentation
"},{"location":"CHANGELOG/#2783-2022-04-08","title":"[2.78.3] 2022-04-08","text":"
  • Add a retrofit command to retrieve changes made directly in an org
"},{"location":"CHANGELOG/#2782-2022-04-08","title":"[2.78.2] 2022-04-08","text":"
  • Fix legacy API command display (#225)
"},{"location":"CHANGELOG/#2781-2022-04-07","title":"[2.78.1] 2022-04-07","text":"
  • Fix CI & remove docker image with sfdx-cli@stable as it does not exists anymore
"},{"location":"CHANGELOG/#2780-2022-04-07","title":"[2.78.0] 2022-04-07","text":"
  • New parameter --skipauth on all hardis commands, to allow the auth check when a default username is required (allows advanced users to improve performances)
  • Set user email when fetching a scratch org from scratch org pool
"},{"location":"CHANGELOG/#2772-2022-04-07","title":"[2.77.2] 2022-04-07","text":"
  • Fix bug when subtracting a package.xml from another
"},{"location":"CHANGELOG/#2771-2022-04-07","title":"[2.77.1] 2022-04-07","text":"
  • Fix error in packageDeployOnce.xml document (sfdx hardis:project:deploy:sources:dx)
"},{"location":"CHANGELOG/#2770-2022-04-05","title":"[2.77.0] 2022-04-05","text":"
  • Generate deployment tips documentation
  • hardis:org:user:activateinvalid : new --profiles argument
  • Update MsTeams WebHooks ENV variables
    • MS_TEAMS_WEBHOOK_URL_CRITICAL
    • MS_TEAMS_WEBHOOK_URL_SEVERE
    • MS_TEAMS_WEBHOOK_URL_WARNING
    • MS_TEAMS_WEBHOOK_URL_INFO
  • Allow to install packages during deployment check using INSTALL_PACKAGES_DURING_CHECK_DEPLOY=true env variable
  • Enhance prompt org labels
"},{"location":"CHANGELOG/#2762-2022-04-04","title":"[2.76.2] 2022-04-04","text":"
  • Improve activate invalid users commands (allow to select by profile(s))
"},{"location":"CHANGELOG/#2761-2022-04-04","title":"[2.76.1] 2022-04-04","text":"
  • Improve activate invalid users commands
"},{"location":"CHANGELOG/#2760-2022-04-03","title":"[2.76.0] 2022-04-03","text":"
  • New command sfdx hardis:org:user:activateinvalid to activate invalid emails in sandbox
  • Fix CI org authentication in case the default username is not the org that we want to configure
  • Bypass error with force:source:legacy:pull / push
  • hardis:work:save : Propose to manually commit files
  • Fix hardis:org:select alias & user config
  • Colorize command lines in logs
  • Enhance new task with sandbox (not fully stable yet)
  • New deployTips
    • Please choose a different name
"},{"location":"CHANGELOG/#2750-2022-03-28","title":"[2.75.0] 2022-03-28","text":"
  • Property availableTargetBranches can be defined in .sfdx-hardis.yml to list the possible target branches for merge requests
  • fix hardis:work:save to propose a git push when the current branch is ahead of origin branch
  • New deployTips
    • XML item appears more than once
"},{"location":"CHANGELOG/#2742-2022-03-26","title":"[2.74.2] 2022-03-26","text":"
  • Update legacy API detection labels
"},{"location":"CHANGELOG/#2741-2022-03-25","title":"[2.74.1] 2022-03-25","text":"
  • Manage crash when retrieving metadatas from CI jobs
"},{"location":"CHANGELOG/#2740-2022-03-24","title":"[2.74.0] 2022-03-24","text":"
  • Enhance hardis:work:save to request if the files has already been staged and committed
  • Deploy manifest and destructive change in the same sfdx force:source:deploy call thanks to new argument postdestructivechanges
  • More deployTips
  • Improve MsTeams notifications management
"},{"location":"CHANGELOG/#2730-2022-03-21","title":"[2.73.0] 2022-03-21","text":"
  • Improve tips about how to fix deployments directly within error messages
  • Wrapper commands to display tips in error logs
    • force:source:deploy can be wrapped using hardis:source:deploy
    • force:source:push can be wrapped using hardis:source:push
    • force:mdapi:deploy can be wrapped using hardis:mdapi:deploy
"},{"location":"CHANGELOG/#2720-2022-03-21","title":"[2.72.0] 2022-03-21","text":"
  • Include tips about how to fix deployments directly within error messages
"},{"location":"CHANGELOG/#2712-2022-03-17","title":"[2.71.2] 2022-03-17","text":"
  • Update JSON schema for customCommands (used by VsCode SFDX Hardis)
  • New property for scratch org pool config: maxScratchOrgsNumberToCreateOnce (max number of scratch orgs to create during one CI job)
"},{"location":"CHANGELOG/#2710-2022-03-15","title":"[2.71.0] 2022-03-15","text":"
  • New command hardis:org:data:delete to manage delete data workspaces of sfdmu
  • New command hardis:scratch:pool:reset to delete all scratch orgs from a scratch orgs pool (like when a new project-scratch-def is delivered)
"},{"location":"CHANGELOG/#2700-2022-03-10","title":"[2.70.0] 2022-03-10","text":"
  • hardis:org:apex:test : allow command to succeed when no tests are present in the project, useful for new environments initialization
"},{"location":"CHANGELOG/#2690-2022-03-02","title":"[2.69.0] 2022-03-02","text":"
  • Scratch org pool: add history (fetch,auth) on ActiveScratchOrg devhub record
"},{"location":"CHANGELOG/#2686-2022-02-22","title":"[2.68.6] 2022-02-22","text":"
  • remove DEPLOY PROGRESS noisy lines from logs
"},{"location":"CHANGELOG/#2685-2022-02-18","title":"[2.68.5] 2022-02-18","text":"
  • Update mkdocs
  • fix commit of files with spaces
"},{"location":"CHANGELOG/#2684-2022-02-18","title":"[2.68.4] 2022-02-18","text":"
  • hardisinstall
    • Add -k, --installationkey CLI param and prompts user for it if not supplied
"},{"location":"CHANGELOG/#2683-2022-02-18","title":"[2.68.3] 2022-02-18","text":"
  • Fix hardisversion:promote --auto
"},{"location":"CHANGELOG/#2682-2022-02-15","title":"[2.68.2] 2022-02-15","text":"
  • Fix minimize profiles command
"},{"location":"CHANGELOG/#2681-2022-02-02","title":"[2.68.1] 2022-02-02","text":"
  • Allow property autoRemoveUserPermissions in .sfdx-hardis.yml to clean profiles
  • toml2csv:
    • Add concatComposite option for column
    • Add recordType option for column
"},{"location":"CHANGELOG/#2680-2022-01-31","title":"[2.68.0] 2022-01-31","text":"
  • Do not create log files in the current directory if it is empty
  • More deployTips
  • Clean MDAPI output logs from progression lines
  • Add listViewMine in cleaning references
  • toml2csv updates
"},{"location":"CHANGELOG/#2671-2022-01-20","title":"[2.67.1] 2022-01-20","text":"
  • Enhance documentation for hardis:scratch:pool:create command
  • Fixes and enhancements on toml2csv command
"},{"location":"CHANGELOG/#2670-2022-01-18","title":"[2.67.0] 2022-01-18","text":"
  • hardis:misc:toml2csv enhancements (rename and copy files)
  • fix minimizing of profiles
  • new command hardis:project:clean:listview
"},{"location":"CHANGELOG/#2662-2022-01-13","title":"[2.66.2] 2022-01-13","text":"
  • hardis:misc:toml2csv enhancements
"},{"location":"CHANGELOG/#2661-2022-01-11","title":"[2.66.1] 2022-01-11","text":"
  • minimizeProfiles: do not remove userPermissions if profile is default Admin profile
"},{"location":"CHANGELOG/#2660-2022-01-07","title":"[2.66.0] 2022-01-07","text":"
  • Check deployment with metadata project
"},{"location":"CHANGELOG/#2650-2022-01-05","title":"[2.65.0] 2022-01-05","text":"
  • Fix contribution install by upgrading dependencies
  • Use soqlQuery method everywhere
  • Set devhub alias when available
"},{"location":"CHANGELOG/#2641-2021-12-29","title":"[2.64.1] 2021-12-29","text":"
  • Update default apiVersion to 53.0
  • Option to not remove empty types when subtracting package.xml
"},{"location":"CHANGELOG/#2640-2021-12-24","title":"[2.64.0] 2021-12-24","text":"
  • New command hardis:clean:minimizeprofiles
  • New deployTip duplicate-value-platform-action-id-list
  • Apply packageDeployOnce.xml and packageDeployOnChange.xml in all contexts
  • Package.xml mixing: fix wildcard <members>*</members> management
  • List metadatas of target org: complete with what sfpowerkit commands does not return (ListView,CustomLabel)
"},{"location":"CHANGELOG/#2630-2021-12-21","title":"[2.63.0] 2021-12-21","text":"
  • New event message refreshPlugins (used by VsCodeSFDX Hardis)
  • Display Error message when unable to delete a temporary directory
"},{"location":"CHANGELOG/#2620-2021-12-14","title":"[2.62.0] 2021-12-14","text":"
  • Fix hardis:work:save crash when rebuilding deploymentPlan
  • Fix XML indentation (#51). Can also be overridden by using env variable SFDX_XML_INDENT (ex: SFDX_INDENT=' ')
"},{"location":"CHANGELOG/#2610-2021-12-02","title":"[2.61.0] 2021-12-02","text":"
  • Use same XML indentation than Salesforce (#51) (requires also upgrade of sfdx-essentials, using sfdx plugins:install sfdx-essentials)
"},{"location":"CHANGELOG/#2603-2021-11-08","title":"[2.60.3] 2021-11-08","text":"
  • Fix hardis:source:pull when there are errors
"},{"location":"CHANGELOG/#2602-2021-11-06","title":"[2.60.2] 2021-11-06","text":"
  • Allow to input URL to use to login
"},{"location":"CHANGELOG/#2601-2021-11-05","title":"[2.60.1] 2021-11-05","text":"
  • Fix hardis:scratch:pool:view when DevHub authentication is expired
"},{"location":"CHANGELOG/#2600-2021-11-03","title":"[2.60.0] 2021-11-03","text":"
  • Deployment failure: Tuning of error message + display of direct link to Deployment Status page in console logs
  • When not in CI, prompt for the org to use to simulate deployments
"},{"location":"CHANGELOG/#2590-2021-11-03","title":"[2.59.0] 2021-11-03","text":"
  • (ALPHA,not really usable yet) Allow to use sandboxes for new task (create from production org, or clone from other sandbox)
  • Fixes about scratch org initialization and JWT auth configuration
"},{"location":"CHANGELOG/#2583-2021-10-23","title":"[2.58.3] 2021-10-23","text":"
  • hardis:org:files:export: Fix file paths in logs
"},{"location":"CHANGELOG/#2582-2021-10-18","title":"[2.58.2] 2021-10-18","text":"
  • org:user:freeze : Prevent to freeze all profiles and current user profile
"},{"location":"CHANGELOG/#2581-2021-10-18","title":"[2.58.1] 2021-10-18","text":"
  • org:retrieve:sources:metadata : Manage locally defined remove-items-package.xml (that can handle wildcard members)
"},{"location":"CHANGELOG/#2580-2021-10-16","title":"[2.58.0] 2021-10-16","text":"
  • org:retrieve:sources:metadata : Run apex tests and legacy api check if we are in CI and in a repository named with monitoring
  • Teams notifications for apex tests and legacy api failure
"},{"location":"CHANGELOG/#2572-2021-10-13","title":"[2.57.2] 2021-10-13","text":"
  • hardis:org:files:export
    • Add file extension when missing
    • replace .snote by .txt
    • replace special characters in parent folder name and file name
"},{"location":"CHANGELOG/#2571-2021-10-12","title":"[2.57.1] 2021-10-12","text":"
  • Retry when BULK API Query returns a timeout
  • hardis:org:files:export
    • Use node-fetch-retry for direct downloads (retry up to 30 seconds by default)
    • New argument --startchunknumber to start files extraction from a chunk position
"},{"location":"CHANGELOG/#2570-2021-10-11","title":"[2.57.0] 2021-10-11","text":"
  • Make hardis:org:user:freeze and hardis:org:user:unfreeze can now handle large volume of users, using Bulk API
"},{"location":"CHANGELOG/#2560-2021-10-10","title":"[2.56.0] 2021-10-10","text":"
  • Update auto-generated documentation to add a commands.md + its link in the menu
"},{"location":"CHANGELOG/#2553-2021-10-05","title":"[2.55.3] 2021-10-05","text":"
  • When not in CI, disable auto-update of .gitignore and .forceignore files because of a prompt library issue. To enable it, define AUTO_UPDATE env variable to \"true\"
"},{"location":"CHANGELOG/#2552-2021-10-03","title":"[2.55.2] 2021-10-03","text":"
  • Fix link to https://nicolas.vuillamy.fr/handle-salesforce-api-versions-deprecation-like-a-pro-335065f52238
"},{"location":"CHANGELOG/#2551-2021-10-01","title":"[2.55.1] 2021-10-01","text":"
  • SFDX_HARDIS_DEBUG_ENV. If set to true, display env vars at startup
"},{"location":"CHANGELOG/#2550-2021-10-01","title":"[2.55.0] 2021-10-01","text":"
  • Manage env var SFDX_HARDIS_DEPLOY_IGNORE_SPLIT_PACKAGES. If \"true\", package.xmls are not split with deploymentPlan
"},{"location":"CHANGELOG/#2540-2021-09-27","title":"[2.54.0] 2021-09-27","text":"
  • Allow to override force:org:create waiting time using SCRATCH_ORG_WAIT en variable (default: 15mn)
  • hardis:org:select : new parameter --scratch to allow to list only scratch orgs related to current Dev Hub
  • hardis:org:retrieve:sources:dx2 : New parameter --template to use default package.xml files (ex: wave)
  • Scratch org pool: automatically delete too old ready-to-use scratch orgs
  • Deploy Tips
    • Wave deployment error
"},{"location":"CHANGELOG/#2531-2021-09-14","title":"[2.53.1] 2021-09-14","text":"
  • Update Object deployed when configuring scratch org pool (replace Html by LongTextArea)
"},{"location":"CHANGELOG/#2530-2021-09-14","title":"[2.53.0] 2021-09-14","text":"
  • Additional docker images, to use when stable and latest sfdx-cli versions arr broken
    • hardisgroupcom/sfdx-hardis:latest-sfdx-recommended
    • hardisgroupcom/sfdx-hardis:beta-sfdx-recommended
    • hardisgroupcom/sfdx-hardis:alpha-sfdx-recommended
"},{"location":"CHANGELOG/#2520-2021-09-14","title":"[2.52.0] 2021-09-14","text":"
  • New command hardis:project:fix:v53flexipages to fix v53.0 broken ascending compatibility
  • New command hardis:project:audit:duplicatefiles to detect doubling files in wrong sfdx folders
"},{"location":"CHANGELOG/#2516-2021-09-10","title":"[2.51.6] 2021-09-10","text":"
  • Take in account parameter --ignore-whitespace of sfdx-git-delta for packageOnChange.xml
"},{"location":"CHANGELOG/#2515-2021-09-10","title":"[2.51.5] 2021-09-10","text":"
  • hardis:org:diagnose:legacyapi: Provide additional report with unique list of ips, hostnames (when available) , and number of calls
  • Fix hardisversion:promote
"},{"location":"CHANGELOG/#2514-2021-09-03","title":"[2.51.4] 2021-09-03","text":"
  • hardis:org:diagnose:legacyapi: Allow to override default output reportfile with --outputfile argument
"},{"location":"CHANGELOG/#2513-2021-09-02","title":"[2.51.3] 2021-09-02","text":"
  • Improve authentication log + less cases when launching again the same command can be necessary
  • if you define forceRestDeploy: true in config, restDeploy: false won't be set automatically anymore
"},{"location":"CHANGELOG/#2512-2021-08-31","title":"[2.51.2] 2021-08-31","text":"
  • Quick fixes hardis:doc:plugin:generate
    • Fix crash when there are no license & changelog
"},{"location":"CHANGELOG/#2511-2021-08-31","title":"[2.51.1] 2021-08-31","text":"
  • Quick fixes hardis:doc:plugin:generate
    • Handle when command.title or command.description is empty
    • Add # Commands to the README.md truncate markers
  • Fix hardis:org:retrieve:sources:dx
    • Empty temp directories at the beginning of the command
    • Add ForecastingType in the list of ignored metadatas for conversion to sfdx sources
"},{"location":"CHANGELOG/#2510-2021-08-31","title":"[2.51.0] 2021-08-31","text":"
  • Update hardis:doc:plugin:generate so main README part is displayed on doc index.md
"},{"location":"CHANGELOG/#2500-2021-08-30","title":"[2.50.0] 2021-08-30","text":"
  • New commands to freeze users before deployment then unfreeze users after deployment
    • sfdx hardis:org:user:freeze
    • sfdx hardis:org:user:unfreeze
"},{"location":"CHANGELOG/#2491-2021-08-30","title":"[2.49.1] 2021-08-30","text":"
  • QuickFix scratch org auth during CI
"},{"location":"CHANGELOG/#2490-2021-08-30","title":"[2.49.0] 2021-08-30","text":"
  • Manage scratch org pools to enhance performances
    • Initialize configuration with hardis:scratch:pool:configure
    • Fetch a new scratch org from the pool when requesting creation of a new scratch org
"},{"location":"CHANGELOG/#2481-2021-08-27","title":"[2.48.1] 2021-08-27","text":"
  • QuickFix hardis:org:files:export
"},{"location":"CHANGELOG/#2480-2021-08-27","title":"[2.48.0] 2021-08-27","text":"
  • New command hardis:org:files:export to download all files (ContentVersion) attached to records (ex: Opportunity)
  • Generate text log file in hardis-report/commands when sfdx-hardis is not run from CI
  • hardis:org:diagnose:legacyapi : simpler logs
"},{"location":"CHANGELOG/#2473-2021-08-23","title":"[2.47.3] 2021-08-23","text":"
  • hardis:org:diagnose:legacyapi: Add more summary and statistics
"},{"location":"CHANGELOG/#2472-2021-08-23","title":"[2.47.2] 2021-08-23","text":"
  • Fix hardis:org:diagnose:legacyapi (display raw logs when CSV builder is crashing) , using papaparse instead of objects-to-csv package
"},{"location":"CHANGELOG/#2471-2021-08-19","title":"[2.47.1] 2021-08-19","text":"
  • Use --permissivediff to call sfdx-git-delta if the argument is available
  • Manage env vars SKIP_PACKAGE_DEPLOY_ON_CHANGE and SKIP_PACKAGE_DEPLOY_ONCE . If set to true, related packageDeployOnChange.xml and packageDeployOnce.xml are ignored
  • Define locally method to remove package.xml from another, to improve performances
"},{"location":"CHANGELOG/#2470-2021-08-19","title":"[2.47.0] 2021-08-19","text":"
  • New feature: use packageDeployOnChange.xml, to skip deployment of items that has not been updated since last update
  • Create docker images with sfdx-cli@stable version
    • alpha-sfdx-stable
    • beta-sfdx-stable
    • latest-sfdx-stable
"},{"location":"CHANGELOG/#2460-2021-08-16","title":"[2.46.0] 2021-08-16","text":"
  • Allow to run git delta command on local updates
  • Update labels of hardis:data commands
  • New technical command: hardis:work:ws , to call VsCode Extension refresh from CLI
"},{"location":"CHANGELOG/#2450-2021-08-15","title":"[2.45.0] 2021-08-15","text":"
  • Refactor hardis:org:diagnose:legacyapi with jsforce to handle more log entries
  • Do not display git branch -v in logs
"},{"location":"CHANGELOG/#2440-2021-08-14","title":"[2.44.0] 2021-08-14","text":"
  • New command hardis:org:diagnose:legacyapi : Detect use of deprecated API versions in production org
"},{"location":"CHANGELOG/#2431-2021-07-23","title":"[2.43.1] 2021-07-23","text":"
  • Update deployTips
  • Update json schema
"},{"location":"CHANGELOG/#2430-2021-07-22","title":"[2.43.0] 2021-07-22","text":"
  • Better split of elements during hardis:work:save
  • Display elapsed time for long running commands
"},{"location":"CHANGELOG/#2422-2021-07-20","title":"[2.42.2] 2021-07-20","text":"
  • Use relative path for sfdmu data import/export
"},{"location":"CHANGELOG/#2421-2021-07-19","title":"[2.42.1] 2021-07-19","text":"
  • Fix data import & export commands when spaces in folder names
"},{"location":"CHANGELOG/#2420-2021-07-12","title":"[2.42.0] 2021-07-12","text":"
  • New command sfdx hardis:project:lint
  • Update .sfdx-hardis.yml configuration JsonSchema
"},{"location":"CHANGELOG/#2412-2021-07-12","title":"[2.41.2] 2021-07-12","text":"
  • QuickFix case when title is not set (use first line of description)
"},{"location":"CHANGELOG/#2411-2021-07-12","title":"[2.41.1] 2021-07-12","text":"
  • Quickfix default mkdocs.yml
"},{"location":"CHANGELOG/#2410-2021-07-12","title":"[2.41.0] 2021-07-12","text":"
  • Add JSON Schema for .sfdx-hardis.yml configuration files
  • Automatic SFDX Plugin documentation generation for any SFDX Plugin
"},{"location":"CHANGELOG/#2400-2021-07-08","title":"[2.40.0] 2021-07-08","text":"
  • hardis:scratch:create: Initialize data using SFDMU, if defined in .sfdx-hardis.json dataPackages property with importInScratchOrgs: true
    • Example
dataPackages:\n  - dataPath: scripts/data/LightningSchedulerConfig\n    importInScratchOrgs: true\n
  • Propose to update or not default target git branch
  • List target git branches if defined in .sfdx-hardis.json availableTargetBranches property
  • hardis:scratch:delete: Propose only scratch orgs related to currently selected Dev Hub
  • New command hardis:org:configure:data to initialize a SFDMU project, sfdx-hardis flavored
  • Display data package label & description, from SFDMU folder config.json properties sfdxHardisLabel and sfdxHardisDescription
  • hardis:org:data:import & hardis:org:data:import: Allow to select current org or another when running data import/export commands
  • Display Dev Hub username when listing orgs for selection
"},{"location":"CHANGELOG/#2311-2021-07-02","title":"[2.31.1] 2021-07-02","text":"
  • hardis:scratch:delete : Display instanceUrl & last usage of scratch orgs displayed before deletion
"},{"location":"CHANGELOG/#2310-2021-07-02","title":"[2.31.0] 2021-07-02","text":"
  • New command hardis:scratch:delete to delete scratch orgs locally referenced.
"},{"location":"CHANGELOG/#2301-2021-06-30","title":"[2.30.1] 2021-06-30","text":"
  • hardis:org:connect : Propose user to open org in browser if not in CI
"},{"location":"CHANGELOG/#2300-2021-06-30","title":"[2.30.0] 2021-06-30","text":"
  • Update hardis:org:retrieve:packageconfig so it allows to select an org, and to update sfdx-hardis configuration
"},{"location":"CHANGELOG/#2290-2021-06-29","title":"[2.29.0] 2021-06-29","text":"
  • New command hardis:org:retrieve:sources:dx2 to assist call to force:source:retrieve using a package.xml file
  • Improve hardis:project:generate:gitdelta by allowing to select commits from their description
  • Use magenta to display config file updates
"},{"location":"CHANGELOG/#2280-2021-06-23","title":"[2.28.0] 2021-06-23","text":"
  • CI: Check Docker image security with trivy
  • Avoid git error when development branch is updated
"},{"location":"CHANGELOG/#2271-2021-06-21","title":"[2.27.1] 2021-06-21","text":"
  • Fix CountryCode when updating scratch org user. Default FR - France, can be updated with config defaultCountry and defaultCountryCode in .sfdx-hardis.yml
"},{"location":"CHANGELOG/#2270-2021-06-20","title":"[2.27.0] 2021-06-20","text":"
  • Clean Lookup filters before force:source:push, then restore them and push again
  • Manage gitRootFolderPrefix config property, in case the root of git repository is at a parent level than sfdx project root
  • Allow to override separate deployments using config property separateDeploymentsConfig
  • Set git config core.quotepath to false to manage special characters in git files / folders
  • Run sfdx git delta at the root of the git repository
  • Rename DeferSharingCalc permission set into SfdxHardisDeferSharingCalc
  • New Deployment tips
  • Contributing documentation
"},{"location":"CHANGELOG/#2264-2021-06-18","title":"[2.26.4] 2021-06-18","text":"
  • Do not write user config when current folder is empty
"},{"location":"CHANGELOG/#2261-2021-06-17","title":"[2.26.1] 2021-06-17","text":"
  • Take in account testLevel from .sfdx-hardis.yml in deployments
"},{"location":"CHANGELOG/#2260-2021-06-16","title":"[2.26.0] 2021-06-16","text":"
  • New command hardis:project:generate:gitdelta to generate the package.xml calculated between two commits
  • New command hardis:org:connect to connect to an org without selecting it (can be used to refresh expired token)
  • Propose choice to to skip .gitignore & .forceignore files auto-update
  • Define triggerNotification on Command class to trigger MsTeams notifs
  • Update org type selection message
"},{"location":"CHANGELOG/#2253-2021-06-14","title":"[2.25.3] 2021-06-14","text":"
  • Fix bug when selecting an org from outside a SFDX project folder
"},{"location":"CHANGELOG/#2252-2021-06-14","title":"[2.25.2] 2021-06-14","text":"
  • Refresh VsCode Sfdx Hardis UI when creating / loading a SFDX Project
"},{"location":"CHANGELOG/#2251-2021-06-13","title":"[2.25.1] 2021-06-13","text":"
  • Check if folder is a git repo before updating git config
"},{"location":"CHANGELOG/#2250-2021-06-12","title":"[2.25.0] 2021-06-12","text":"
  • New parameter keepmetadatatypes for hardis:org:retrieve:sources:dx
  • Check dependencies
    • Improve performances
    • Check application dependencies (git,openssl)
"},{"location":"CHANGELOG/#2240-2021-06-10","title":"[2.24.0] 2021-06-10","text":"
  • New command hardis:org:purge:apexlog to purge all Apex Logs of selected org
"},{"location":"CHANGELOG/#2230-2021-06-07","title":"[2.23.0] 2021-06-07","text":"
  • Manage installation key for unlocked packages installation
  • Deployment: manage --canmodify SFDMU argument (define sfdmuCanDeploy in sfdx-hardis branch config file)
"},{"location":"CHANGELOG/#2220-2021-06-03","title":"[2.22.0] 2021-06-03","text":"
  • New command hardis:project:clean:orgmissingitems : Remove elements that are not existing in target org (only in ReportType for now)
  • hardis:project:clean:references : Remove cleaned items from package.xml files
  • Externalization of method to select an org (+ reorder of list of displayed orgs)
"},{"location":"CHANGELOG/#2210-2021-06-02","title":"[2.21.0] 2021-06-02","text":"
  • hardis:project:clean:references: Improve performances for removing files
  • hardis:scratch:create : Shorten scratch org auto-generated name
  • Authenticate to an org: Request user to set alias if not provided
  • Update default gitlab-ci.yml
  • New method promptProfiles
"},{"location":"CHANGELOG/#2203-2021-05-26","title":"[2.20.3] 2021-05-26","text":"
  • Set prompt UI timeout to 2h instead of 5mn
"},{"location":"CHANGELOG/#2202-2021-05-25","title":"[2.20.2] 2021-05-25","text":"
  • Fix call to sfdmu (add --noprompt)
"},{"location":"CHANGELOG/#2201-2021-05-23","title":"[2.20.1] 2021-05-23","text":"
  • Fix scratch org listing
"},{"location":"CHANGELOG/#2200-2021-05-21","title":"[2.20.0] 2021-05-21","text":"
  • hardis:work:save : Prompt user to pull from scratch org or not before saving
  • Do not update package.json anymore
  • hardis:scratch:create : Fix reuse scratch org prompt
"},{"location":"CHANGELOG/#2190-2021-05-20","title":"[2.19.0] 2021-05-20","text":"
  • Detect when auth token is expired
  • More deploy tips
  • Clean ProductRequest items
"},{"location":"CHANGELOG/#2180-2021-05-18","title":"[2.18.0] 2021-05-18","text":"
  • New commands

    • hardis:org:retrieve:packageconfig: Retrieves .sfdx-hardis.yml property installedPackaged from an existing org
    • hardis:project:clean:emptyitems: Delete empty items from SFD project
    • hardis:project:clean:hiddenitems: Delete hidden items (from managed packages) from SFDX project
  • Update default values for JWT connected app creation
  • Manage --targetusername to be taken in account for all sfdx hardis commands
  • More deployment tips
  • hardis:project:clean:manageditems: New --namespace argument
  • org:retrieve:source:dx : Do not erase .gitignore, .forceignore , README.md and project-scratch-def is already existing locally
  • Remove shape temp folder to avoid a force:org:create bug
"},{"location":"CHANGELOG/#2173-2021-05-18","title":"[2.17.3] 2021-05-18","text":"
  • Fix .gitignore automatic update constraint
"},{"location":"CHANGELOG/#2172-2021-05-10","title":"[2.17.2] 2021-05-10","text":"
  • Default init scratch org using push and not deploy
  • QuickFix mergeRequest links local storage
"},{"location":"CHANGELOG/#2170-2021-05-10","title":"[2.17.0] 2021-05-10","text":"
  • New command hardis:project:convert:profilestopermsets to convert all profiles into permission sets
  • hardis:scratch:create : Fix permission set auto assignment when creating a scratch org (use property initPermissionSets in .sfdx-hardis.yml)
"},{"location":"CHANGELOG/#2161-2021-05-09","title":"[2.16.1] 2021-05-09","text":"
  • hardis:work:save : Fix storage in config file of Merge Request info
  • Update deploy tips
"},{"location":"CHANGELOG/#2160-2021-05-08","title":"[2.16.0] 2021-05-08","text":"
  • hardis:project:clean:manageditems : Clean SFDX project from managed classes
  • hardis:project:clean:retrievefolders: Clean/Complete SFDX project with missing folders (dashboard,email,reports)
  • hardis:project:clean:standarditems : Clean SFDX project from objects with no custom within
  • More deployment error tips
  • New parameter websocket for all commands
  • Indicating in logs when deployment is a simulation
"},{"location":"CHANGELOG/#2151-2021-05-02","title":"[2.15.1] 2021-05-02","text":"
  • QuickFix hardis:work:save
"},{"location":"CHANGELOG/#2150-2021-04-30","title":"[2.15.0] 2021-04-30","text":"
  • hardis:project:clean:references : New cleaning module dashboards removing reference to users in Dashboards sources
"},{"location":"CHANGELOG/#2140-2021-04-29","title":"[2.14.0] 2021-04-29","text":"
  • Manage manifest/packageDeployOnce.xml : all its items that are already present in target org will not be deployed again
"},{"location":"CHANGELOG/#2134-2021-04-26","title":"[2.13.4] 2021-04-26","text":"
  • New deploy tips
  • Do not update local files when calling configure commands
  • hardis:work:save : Fix branch update issue
"},{"location":"CHANGELOG/#2133-2021-04-23","title":"[2.13.3] 2021-04-23","text":"
  • Remove PMD rule :
    • CyclomaticComplexity
"},{"location":"CHANGELOG/#2132-2021-04-22","title":"[2.13.2] 2021-04-22","text":"
  • QuickFix hardisversion:promote --auto
"},{"location":"CHANGELOG/#2130-2021-04-21","title":"[2.13.0] 2021-04-21","text":"
  • hardis:work:save
    • New parameter --nogit for expert developers who want to manage git operations themselves
    • New parameter --noclean for expert developers who want to manage clean operations themselves
  • Update default Mega-Linter config
"},{"location":"CHANGELOG/#2120-2021-04-19","title":"[2.12.0] 2021-04-19","text":"
  • New variable CI_DEPLOY_QUICK_ACTIONS_DUMMY
    • set to \"true\" in CI variables when there are QuickActions dependent of Flows that are later in publication plan
    • then set again to \"false\" and the deployment will pass :)
  • hardis:project:clean:references : now deletes obsolete objects and objectTranslations
  • hardis:work:save : More categories in interactive git add
  • Improve authentication check performances
  • New command hardis:config:get to return all config for project, branch or user
  • New deployment errors tips
"},{"location":"CHANGELOG/#2110-2021-04-15","title":"[2.11.0] 2021-04-15","text":"
  • Delete scratch org when its initialization has failed during CI
  • Clean obsolete object fields and objectTranslations
"},{"location":"CHANGELOG/#2104-2021-04-15","title":"[2.10.4] 2021-04-15","text":"
  • Provide password to user when creating new scratch org
  • Update CI default config to allow to not delete scratch orgs (define CI_DELETE_SCRATCH_ORG: \"true\" in gitlab-ci-config.yml)
  • New deploy tips: record type not found, picklist value not found
"},{"location":"CHANGELOG/#2103-2021-04-14","title":"[2.10.3] 2021-04-14","text":"
  • Allow advanced user to bypass auth check (set skipAuthCheck:true in config/user/***.sfdx-hardis.yml)
  • Optimize check of force:config:set restDeploy: false
  • hardisversion:create : Store package installation password in project config + fixes
"},{"location":"CHANGELOG/#2102-2021-04-14","title":"[2.10.2] 2021-04-14","text":"
  • hardis:work:refresh : Make sure the user saved his work (commit) before merging another branch in current branch
"},{"location":"CHANGELOG/#2101-2021-04-11","title":"[2.10.1] 2021-04-11","text":"
  • hardis:org:test:apex : Fix regex to new Apex Test results stdout format
"},{"location":"CHANGELOG/#2100-2021-04-11","title":"[2.10.0] 2021-04-11","text":"
  • hardis:work:save : Automatic generation of split package.xml and deploymentPlan in .sfdx-hardis.yml
  • hardis:work:save : Propose to export data when saving
  • Remove duplicates from .gitignore and .forceignore
  • Add chromium in dockerfile
"},{"location":"CHANGELOG/#294-2021-04-09","title":"[2.9.4] 2021-04-09","text":"
  • Fix refresh
  • Update project cleaning references
"},{"location":"CHANGELOG/#293-2021-04-08","title":"[2.9.3] 2021-04-08","text":"
  • hardis:work:refresh : allow to refresh from another branch
"},{"location":"CHANGELOG/#292-2021-04-08","title":"[2.9.2] 2021-04-08","text":"
  • hardis:work:save : Fix issue when trying to stage & commit ignored files after project cleaning
  • hardis:project:configure:auth Improve error message when unable to upload ConnectedApp on production environment
  • Update default Apex PMD ruleset
  • Use replace and not replaceAll for node14 compatibility
"},{"location":"CHANGELOG/#291-2021-04-07","title":"[2.9.1] 2021-04-07","text":"
  • Clean git reset before save
  • Clean git stash before new task
"},{"location":"CHANGELOG/#290-2021-04-06","title":"[2.9.0] 2021-04-06","text":"
  • New command hardis:project:create
  • Refactor project cleaning and allow to use external config files (destructiveChanges-like.xml or json)
  • Fixes
    • hardis:work:save : Create destructiveChanges.xml if not existing
    • hardis:work:save : call forceSourcePull method to propose to update .forceignore if errors are found
    • hardis:project:configure:auth: call mdapi:deploy with RunLocalTests to manage production environments
    • authentication: auth only to devHub if --devhub sent
    • Disable spinner for restDeploy check
"},{"location":"CHANGELOG/#285-2021-04-06","title":"[2.8.5] 2021-04-06","text":"
  • QuickFix question icon
"},{"location":"CHANGELOG/#284-2021-04-06","title":"[2.8.4] 2021-04-06","text":"
  • Allow to skip pull before save
  • New deployTip: code coverage items with 0%
  • Fix DevHub auth when credential out of date
  • Use latest sfdx-cli package
  • Init git config only if we are not in CI
"},{"location":"CHANGELOG/#283-2021-04-01","title":"[2.8.3] 2021-04-01","text":"
  • Fix package creation
  • When using VsCode UI via WebSocket, display selected values in console logs
"},{"location":"CHANGELOG/#282-2021-04-01","title":"[2.8.2] 2021-04-01","text":"
  • hardis:work:save : reset ongoing merge if existing
  • Fix git reset call
"},{"location":"CHANGELOG/#280-2021-03-31","title":"[2.8.0] 2021-03-31","text":"
  • Define git user.name and user.email if not set
  • Define VsCode as git merge/diff tool if none is defined
  • Unstash changes (git reset) at the beginning of hardis:work:save
  • Deploy destructive changes after real deployment
  • hardis:project:clean:references now works also to remove references to content of manifest/destructiveChanges.xml
  • hardis:work:save: Clean sfdx project while saving it
  • Factorize temp directory creation
"},{"location":"CHANGELOG/#272-2021-03-30","title":"[2.7.2] 2021-03-30","text":"
  • Check user is sure to want to reuse an existing scratch org
  • Fix hardis:work:refresh
"},{"location":"CHANGELOG/#271-2021-03-29","title":"[2.7.1] 2021-03-29","text":"
  • Fix auto-fix of .gitignore and .forceignore
  • Propose to auto-update .force ignore when there is a pull issue
"},{"location":"CHANGELOG/#270-2021-03-29","title":"[2.7.0] 2021-03-29","text":"
  • Communicate with VsCode SFDX Hardis extension via WebSocket if server is found
  • Send user input prompts to VsCode UI if WebSocket server found
  • Send refreshStatus notifications when context is updated
  • Arrange some messages for better display on UI
"},{"location":"CHANGELOG/#260-2021-03-28","title":"[2.6.0] 2021-03-28","text":"
  • New command hardis:project:clean:references to clean SFDX project from data.com license references
  • hardis:scratch:create: Load sfdmu workspace scripts/data/ScratchInit if existing in , to initialize scratch org data
"},{"location":"CHANGELOG/#250-2021-03-28","title":"[2.5.0] 2021-03-28","text":"
  • New command hardis:source:push
  • New command hardis:source:pull
  • Various mini-fixes
  • Move deploymentPlan.json within .sfdx-hardis.json
  • Retry management for execCommand function. ex: retry: {retryDelay: 30,retryStringConstraint: 'some string present in output', retryMaxAttempts: 5}
"},{"location":"CHANGELOG/#240-2021-03-27","title":"[2.4.0] 2021-03-27","text":"
  • Add sfdmu & sfdx-git-delta in dependencies & Dockerfile
  • Import data with sfdmu
  • Manage data import steps in deploymentPlan.json
  • New command hardis:org:data:export
  • New command hardis:org:data:import
"},{"location":"CHANGELOG/#230-2021-03-26","title":"[2.3.0] 2021-03-26","text":"
  • hardis:work:save: Do not git add manifest files when they have not been updated
  • Select type of org to connect: enhance label
  • Multi-Select default to 9999 items displayed
  • Display tips about deployment failures when they happen
  • Create scratch org: When DeferSharingCalc in features, suspend and resume sharing calc during force:source:push
  • Allow to define a file manifest/deploymentPlan.json to split the deployment into separate package.xml files

Example:

{\n  \"packages\": [\n    {\n      \"label\": \"SharingRulesAccount\",\n      \"packageXmlFile\": \"splits/packageXmlSharingRulesAccount.xml\",\n      \"order\": 10,\n      \"waitAfter\": 60\n    },\n    {\n      \"label\": \"SharingRulesVisit__c\",\n      \"packageXmlFile\": \"splits/packageXmlSharingRulesAccountVisit__c.xml\",\n      \"order\": 10\n    }\n  ]\n}\n
"},{"location":"CHANGELOG/#221-2021-03-23","title":"[2.2.1] 2021-03-23","text":"
  • QuickFix 2.2.1
  • Use RunLocalTests when deploying ConnectedApp metadata to production org
"},{"location":"CHANGELOG/#220-2021-03-23","title":"[2.2.0] 2021-03-23","text":"
  • Enhance security by encrypting SSH private key
"},{"location":"CHANGELOG/#217-2021-03-22","title":"[2.1.7] 2021-03-22","text":"
  • More categories for Interactive Git Add (Aura,LWC, Tech Config)
  • Auto-update .forceignore
  • Fix hardis:org:test:apex
"},{"location":"CHANGELOG/#216-2021-03-20","title":"[2.1.6] 2021-03-20","text":"
  • Fix org authentication check
"},{"location":"CHANGELOG/#215-2021-03-19","title":"[2.1.5] 2021-03-19","text":"
  • Unlimited list of items displayed during interactive git add
  • Uniformize prompts to user
"},{"location":"CHANGELOG/#214-2021-03-17","title":"[2.1.4] 2021-03-17","text":"
  • Deploy with --ignorewarnings
"},{"location":"CHANGELOG/#213-2021-03-17","title":"[2.1.3] 2021-03-17","text":"
  • Fix hardis:retrieve:sources:dx when not in a DX project
  • Fix deloyment of Connected App in production
  • Display more options by page during interactive git add
  • Sort files to git add by group and manage preselection
"},{"location":"CHANGELOG/#212-2021-03-14","title":"[2.1.2] 2021-03-14","text":"
  • Improve package installation
    • Allow to install a package not listed in sfdx-hardis
    • Allow to configure automatic installation during deployments, or not
    • Allow to configure automatic installation during scratch org initialisation, or not
  • Reformat strings when no spaces are allowed in a user input
"},{"location":"CHANGELOG/#211-2021-03-12","title":"[2.1.1] 2021-03-12","text":"
  • Fix hardis:scratch:create when initDataRequests
"},{"location":"CHANGELOG/#210-2021-03-10","title":"[2.1.0] 2021-03-10","text":"
  • New command hardis:data:tree:export
  • scratch:create: Import init data using .sfdx-hardis.yml initDataRequests property
  • scratch:create: Assign to permission set (or PS groups) using .sfdx-hardis.yml initPermissionSets property
"},{"location":"CHANGELOG/#200-2021-03-09","title":"[2.0.0] 2021-03-09","text":"
  • New command hardiscreate to create Managed and Unlocked packages
  • Migrate from tslint to eslint
  • Fix dependencies hell
  • Fix hardis:org:purge:flow with new result format (#49)
"},{"location":"CHANGELOG/#161-2021-03-09","title":"[1.6.1] 2021-03-09","text":"
  • Update sfdx-project.json when installing a package
  • Refresh env & scratch org if same scratch org is reused
  • Update default files for CI & monitoring projects
  • Do not deploy packages from hardis:project:deploy:sources:dx when we are in --check mode !
  • Better output display for hardis:org:test:apex
"},{"location":"CHANGELOG/#160-2021-03-08","title":"[1.6.0] - 2021-03-08","text":"
  • New package commands
    • hardisinstall
    • hardisversion:create
    • hardisversion:list
"},{"location":"CHANGELOG/#151-2021-03-07","title":"[1.5.1] - 2021-03-07","text":"
  • Use shared Mega-Linter configuration
"},{"location":"CHANGELOG/#150-2021-03-05","title":"[1.5.0] 2021-03-05","text":"
  • New command hardis:org:select
  • New command hardis:work:resetselection
  • hardis:work:save: Upgrade package.xml and destructiveChanges.xml from git diff
  • Improve console logging of git operations
"},{"location":"CHANGELOG/#141-2021-03-03","title":"[1.4.1] 2021-03-03","text":"
  • Update default gitlab-ci.yml
  • rename commands:
    • hardis:work:new
    • hardis:work:refresh
    • hardis:work:save
  • cosmetic enhancements
"},{"location":"CHANGELOG/#140-2021-02-28","title":"[1.4.0] 2021-02-28","text":"
  • New work commands to make easier non technical users to use Hardis CI
    • hardis:work:task:new
    • hardis:work:task:save
    • hardis:work:task:refresh
"},{"location":"CHANGELOG/#136-2021-02-26","title":"[1.3.6] 2021-02-26","text":"
  • Quick fix hardis:org:configure:monitoring + colors
"},{"location":"CHANGELOG/#135-2021-02-26","title":"[1.3.5] 2021-02-26","text":"
  • Workaround when --soapdeploy argument is not available
"},{"location":"CHANGELOG/#134-2021-02-25","title":"[1.3.4] 2021-02-25","text":"
  • Reuse msTeamsWebhookUrl during sfdx:org:configure:monitoring prompts
  • Allow to override CONFIG_BRANCH to get forced .sfdx.hardis.BRANCH.yml
"},{"location":"CHANGELOG/#133-2021-02-24","title":"[1.3.3] 2021-02-24","text":"
  • Soap option for force:mdapi:deploy
"},{"location":"CHANGELOG/#132-2021-02-24","title":"[1.3.2] 2021-02-24","text":"
  • Guide user to assign rights to Connected App in sfdx:org:configure:monitoring
"},{"location":"CHANGELOG/#131-2021-02-24","title":"[1.3.1] 2021-02-24","text":"
  • Manage git clone & push for sfdx:org:configure:monitoring
  • Manage upload of connected app metadata for sfdx:org:configure:monitoring
"},{"location":"CHANGELOG/#130-2021-02-23","title":"[1.3.0] 2021-02-23","text":"
  • New command sfdx:project:deploy:sources:metadata
  • Generate .cache folder only when necessary
  • New command sfdx:org:configure:monitoring
"},{"location":"CHANGELOG/#30-remove-use-of-sfdx-node","title":"30: Remove use of sfdx-node","text":""},{"location":"CHANGELOG/#120-2021-02-21","title":"[1.2.0] 2021-02-21","text":"
  • Auto-generate alpha version of plugin package and associated docker image when publishing from branch alpha
  • Manage cache storage for CI dependent jobs (cache, artifacts)
    • .cache/sfdx-hardis/.sfdx
    • .sfdx
    • config/user
  • Improve org authentication
  • New command hardis:org:test
    • Test org coverage and fail if < 75%
  • Installed package management
    • Factorize method
    • Install packages during hardis:project:deploy:sources:dx
  • Allow to reuse scratch org if previous creation failed. Force using --forcenew
  • Improve auto-update of local project sfdx-hardis files
  • Improve console logs
  • Allow to store DevHubSfdxClientId in user sfdx-hardis.yml ( in /user folder)
"},{"location":"CHANGELOG/#24-change-the-way-of-listing-installed-packages","title":"24: Change the way of listing installed packages","text":""},{"location":"CHANGELOG/#26-new-command-sfdx-hardisprojectconfiguredeployments-to-configure-connected-app","title":"26: New command sfdx hardis:project:configure:deployments to configure Connected app","text":""},{"location":"CHANGELOG/#27-check-in-manifest-folder-for-packagexml","title":"27: Check in manifest folder for package.xml","text":""},{"location":"CHANGELOG/#113-2021-02-17","title":"[1.1.3] 2021-02-17","text":"
  • Fix cases when directory is not git
"},{"location":"CHANGELOG/#110-2021-02-17","title":"[1.1.0] 2021-02-17","text":"
  • New command hardis:project:deploy:sources:dx (alpha)
  • New command hardis:project:audit:apiversion
"},{"location":"CHANGELOG/#101-2021-02-15","title":"[1.0.1] 2021-02-15","text":"
  • Fix auth:login to avoid DevHub auth when not necessary
"},{"location":"CHANGELOG/#100-2021-02-15","title":"[1.0.0] 2021-02-15","text":"
  • New command hardis:scratch:create
  • Advanced project initialization using --shape argument for sfdx hardis:org:retrieve:sources:dx
  • Automatic generation of .sfdx-hardis*.yml configuration files
  • Automatic update of project package.json to add sfdx-hardis utilities
"},{"location":"CHANGELOG/#0510-2021-02-12","title":"[0.5.10] 2021-02-12","text":"
  • Allow purges to fail without making sfdx command fail
"},{"location":"CHANGELOG/#055-2021-02-10","title":"[0.5.5] 2021-02-10","text":"
  • Check if installed sfdx-hardis is the latest version, else display a message to advise the user to upgrade to latest
"},{"location":"CHANGELOG/#054-2021-02-09","title":"[0.5.4] 2021-02-09","text":"
  • Fixes:
    • hardis:org:purge:flow: Do not crash in case the Flow is not deletable
"},{"location":"CHANGELOG/#052-2021-02-07","title":"[0.5.2] 2021-02-07","text":"
  • Fixes:
    • --no-prompt argument is ignored
"},{"location":"CHANGELOG/#051-2021-02-04","title":"[0.5.1] 2021-02-04","text":"
  • Fixes:
    • Add more items to metadatas not convertible to sfdx sources
    • Issue when using --sandbox argument
"},{"location":"CHANGELOG/#050-2021-02-03","title":"[0.5.0] 2021-02-03","text":"
  • New command hardis:project:audit:callincallout: Audit sfdx project (or metadatas) sources to list all CallIns and CallOuts from Apex / Triggers code parsing
  • New command hardis:project:audit:remotesites: Audit sfdx project (or metadatas) sources to list all remote site settings of an org
"},{"location":"CHANGELOG/#041-2021-02-01","title":"[0.4.1] 2021-02-01","text":"
  • Fix: Manage Hooks only from hardis namespace commands
"},{"location":"CHANGELOG/#040-2021-02-01","title":"[0.4.0] 2021-02-01","text":"
  • Send MS Teams notifications if set environment variable MS_TEAMS_WEBHOOK_URL or msTeamsWebhookUrl in .sfdx-hardis.yml
"},{"location":"CHANGELOG/#031-2021-01-31","title":"[0.3.1] 2021-01-31","text":"
  • Always regenerate full package.xml before retrieving metadatas
"},{"location":"CHANGELOG/#030-2021-01-31","title":"[0.3.0] 2021-01-31","text":"
  • Build and upload nvuillam/sfdx-hardis docker image when releasing a new version
  • New command force:auth:login + manage login using JWT for CI
"},{"location":"CHANGELOG/#020-2021-01-31","title":"[0.2.0] 2021-01-31","text":"
  • New command sfdx hardis:org:retrieve:sources:metadata : Retrieve all metadata from an org
"},{"location":"CHANGELOG/#011-2021-01-31","title":"[0.1.1] 2021-01-31","text":"
  • New command sfdx hardis:org:retrieve:sources:dx : Create SFDX project from remote org
"},{"location":"CHANGELOG/#001-2021-01-26","title":"[0.0.1] 2021-01-26","text":"
  • New command sfdx hardis:org:purge:flow : Purge Obsolete flow versions to avoid the 50 max versions limit
"},{"location":"cloudity-consulting-partner/","title":"Work with Cloudity","text":""},{"location":"cloudity-consulting-partner/#your-expert-salesforce-partner","title":"Your Expert Salesforce Partner","text":"

At Cloudity, we love sharing our technical expertise, such as sfdx-hardis as Open-Source, but that's just a small part of everything we do !

We provide end-to-end digitalization services for companies, combining technical skills and business expertise to deliver solutions that set the bar high for quality. With the backing of our talented people, we\u2019re aiming to grow our influence and spread our culture based on trust, ambition and empowerment.

By end-2025, our goal is to grow our workforce to more than 500 employees, to sustain profitability and to make Cloudity a go-to market player for top companies and for our partners, Salesforce and Meta.

With experts from Hardis Group, Carrenet and Cloudity having joined forces, we now have more than 350 employees in four countries, serving customers across 30 countries (Europe + US).

Want to know more ? Contact us on our WebSite !

"},{"location":"commands/","title":"Commands","text":""},{"location":"commands/#hardisauth","title":"hardis:auth","text":"Command Title hardis:auth:login"},{"location":"commands/#hardiscache","title":"hardis:cache","text":"Command Title hardis:cache:clear"},{"location":"commands/#hardisconfig","title":"hardis:config","text":"Command Title hardis:config:get"},{"location":"commands/#hardisdeploy","title":"hardis:deploy","text":"Command Title hardis:deploy:quick hardis:deploy:start hardis:deploy:validate"},{"location":"commands/#hardisdoc","title":"hardis:doc","text":"Command Title hardis:doc:extract:permsetgroups hardis:doc:flow2markdown hardis:doc:mkdocs-to-salesforce hardis:doc:packagexml2markdown hardis:doc:plugin:generate hardis:doc:project2markdown"},{"location":"commands/#hardisgit","title":"hardis:git","text":"Command Title hardis:git:pull-requests:extract"},{"location":"commands/#hardislint","title":"hardis:lint","text":"Command Title hardis:lint:access hardis:lint:metadatastatus hardis:lint:missingattributes hardis:lint:unusedmetadatas"},{"location":"commands/#hardismdapi","title":"hardis:mdapi","text":"Command Title hardis:mdapi:deploy"},{"location":"commands/#hardismisc","title":"hardis:misc","text":"Command Title hardis:misc:purge-references hardis:misc:toml2csv"},{"location":"commands/#hardisorg","title":"hardis:org","text":"Command Title hardis:org:community:update hardis:org:configure:data hardis:org:configure:files hardis:org:configure:monitoring hardis:org:connect hardis:org:create hardis:org:data:delete hardis:org:data:export hardis:org:data:import hardis:org:diagnose:audittrail hardis:org:diagnose:instanceupgrade hardis:org:diagnose:legacyapi hardis:org:diagnose:licenses hardis:org:diagnose:releaseupdates hardis:org:diagnose:unused-apex-classes hardis:org:diagnose:unused-connected-apps hardis:org:diagnose:unusedlicenses hardis:org:diagnose:unusedusers hardis:org:files:export hardis:org:files:import hardis:org:fix:listviewmine hardis:org:generate:packagexmlfull hardis:org:monitor:all hardis:org:monitor:backup hardis:org:monitor:limits hardis:org:multi-org-query hardis:org:purge:apexlog hardis:org:purge:flow hardis:org:retrieve:packageconfig hardis:org:retrieve:sources:analytics hardis:org:retrieve:sources:dx hardis:org:retrieve:sources:dx2 hardis:org:retrieve:sources:metadata hardis:org:retrieve:sources:retrofit hardis:org:select hardis:org:test:apex hardis:org:user:activateinvalid hardis:org:user:freeze hardis:org:user:unfreeze"},{"location":"commands/#hardispackage","title":"hardis:package","text":"Command Title hardiscreate hardisinstall hardismergexml hardisversion:create hardisversion:list hardisversion:promote"},{"location":"commands/#hardispackagexml","title":"hardis:packagexml","text":"Command Title hardis:packagexml:append hardis:packagexml:remove"},{"location":"commands/#hardisproject","title":"hardis:project","text":"Command Title hardis:project:audit:apiversion hardis:project:audit:callincallout hardis:project:audit:duplicatefiles hardis:project:audit:remotesites hardis:project:clean:emptyitems hardis:project:clean:filter-xml-content hardis:project:clean:flowpositions hardis:project:clean:hiddenitems hardis:project:clean:listviews hardis:project:clean:manageditems hardis:project:clean:minimizeprofiles hardis:project:clean:orgmissingitems hardis:project:clean:references hardis:project:clean:retrievefolders hardis:project:clean:sensitive-metadatas hardis:project:clean:standarditems hardis:project:clean:systemdebug hardis:project:clean:xml hardis:project:configure:auth hardis:project:convert:profilestopermsets hardis:project:create hardis:project:deploy:notify hardis:project:deploy:quick hardis:project:deploy:simulate hardis:project:deploy:smart hardis:project:deploy:sources:dx hardis:project:deploy:sources:metadata hardis:project:deploy:start hardis:project:deploy:validate hardis:project:fix:profiletabs hardis:project:fix:v53flexipages hardis:project:generate:flow-git-diff hardis:project:generate:gitdelta hardis:project:lint hardis:project:metadata:findduplicates"},{"location":"commands/#hardisscratch","title":"hardis:scratch","text":"Command Title hardis:scratch:create hardis:scratch:delete hardis:scratch:pool:create hardis:scratch:pool:localauth hardis:scratch:pool:refresh hardis:scratch:pool:reset hardis:scratch:pool:view hardis:scratch:pull hardis:scratch:push"},{"location":"commands/#hardissource","title":"hardis:source","text":"Command Title hardis:source:deploy hardis:source:push hardis:source:retrieve"},{"location":"commands/#hardiswork","title":"hardis:work","text":"Command Title hardis:work:new hardis:work:refresh hardis:work:resetselection hardis:work:save hardis:work:ws"},{"location":"commands/#helloworld","title":"hello:world","text":"Command Title hello:world"},{"location":"license/","title":"License","text":"
                GNU AFFERO GENERAL PUBLIC LICENSE\n                   Version 3, 19 November 2007\n

Copyright (C) 2007 Free Software Foundation, Inc. https://fsf.org/ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

                        Preamble\n

The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software.

The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.

Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software.

A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public.

The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version.

An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license.

The precise terms and conditions for copying, distribution and modification follow.

                   TERMS AND CONDITIONS\n

0. Definitions.

\"This License\" refers to version 3 of the GNU Affero General Public License.

\"Copyright\" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.

\"The Program\" refers to any copyrightable work licensed under this License. Each licensee is addressed as \"you\". \"Licensees\" and \"recipients\" may be individuals or organizations.

To \"modify\" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a \"modified version\" of the earlier work or a work \"based on\" the earlier work.

A \"covered work\" means either the unmodified Program or a work based on the Program.

To \"propagate\" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.

To \"convey\" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.

An interactive user interface displays \"Appropriate Legal Notices\" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.

1. Source Code.

The \"source code\" for a work means the preferred form of the work for making modifications to it. \"Object code\" means any non-source form of a work.

A \"Standard Interface\" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.

The \"System Libraries\" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A \"Major Component\", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.

The \"Corresponding Source\" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.

The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.

The Corresponding Source for a work in source code form is that same work.

2. Basic Permissions.

All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.

You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.

Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.

3. Protecting Users' Legal Rights From Anti-Circumvention Law.

No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.

When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.

4. Conveying Verbatim Copies.

You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.

You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.

5. Conveying Modified Source Versions.

You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:

a) The work must carry prominent notices stating that you modified\nit, and giving a relevant date.\n\nb) The work must carry prominent notices stating that it is\nreleased under this License and any conditions added under section\n7.  This requirement modifies the requirement in section 4 to\n\"keep intact all notices\".\n\nc) You must license the entire work, as a whole, under this\nLicense to anyone who comes into possession of a copy.  This\nLicense will therefore apply, along with any applicable section 7\nadditional terms, to the whole of the work, and all its parts,\nregardless of how they are packaged.  This License gives no\npermission to license the work in any other way, but it does not\ninvalidate such permission if you have separately received it.\n\nd) If the work has interactive user interfaces, each must display\nAppropriate Legal Notices; however, if the Program has interactive\ninterfaces that do not display Appropriate Legal Notices, your\nwork need not make them do so.\n

A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an \"aggregate\" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.

6. Conveying Non-Source Forms.

You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:

a) Convey the object code in, or embodied in, a physical product\n(including a physical distribution medium), accompanied by the\nCorresponding Source fixed on a durable physical medium\ncustomarily used for software interchange.\n\nb) Convey the object code in, or embodied in, a physical product\n(including a physical distribution medium), accompanied by a\nwritten offer, valid for at least three years and valid for as\nlong as you offer spare parts or customer support for that product\nmodel, to give anyone who possesses the object code either (1) a\ncopy of the Corresponding Source for all the software in the\nproduct that is covered by this License, on a durable physical\nmedium customarily used for software interchange, for a price no\nmore than your reasonable cost of physically performing this\nconveying of source, or (2) access to copy the\nCorresponding Source from a network server at no charge.\n\nc) Convey individual copies of the object code with a copy of the\nwritten offer to provide the Corresponding Source.  This\nalternative is allowed only occasionally and noncommercially, and\nonly if you received the object code with such an offer, in accord\nwith subsection 6b.\n\nd) Convey the object code by offering access from a designated\nplace (gratis or for a charge), and offer equivalent access to the\nCorresponding Source in the same way through the same place at no\nfurther charge.  You need not require recipients to copy the\nCorresponding Source along with the object code.  If the place to\ncopy the object code is a network server, the Corresponding Source\nmay be on a different server (operated by you or a third party)\nthat supports equivalent copying facilities, provided you maintain\nclear directions next to the object code saying where to find the\nCorresponding Source.  Regardless of what server hosts the\nCorresponding Source, you remain obligated to ensure that it is\navailable for as long as needed to satisfy these requirements.\n\ne) Convey the object code using peer-to-peer transmission, provided\nyou inform other peers where the object code and Corresponding\nSource of the work are being offered to the general public at no\ncharge under subsection 6d.\n

A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.

A \"User Product\" is either (1) a \"consumer product\", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, \"normally used\" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.

\"Installation Information\" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.

If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).

The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.

Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.

7. Additional Terms.

\"Additional permissions\" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.

When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.

Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:

a) Disclaiming warranty or limiting liability differently from the\nterms of sections 15 and 16 of this License; or\n\nb) Requiring preservation of specified reasonable legal notices or\nauthor attributions in that material or in the Appropriate Legal\nNotices displayed by works containing it; or\n\nc) Prohibiting misrepresentation of the origin of that material, or\nrequiring that modified versions of such material be marked in\nreasonable ways as different from the original version; or\n\nd) Limiting the use for publicity purposes of names of licensors or\nauthors of the material; or\n\ne) Declining to grant rights under trademark law for use of some\ntrade names, trademarks, or service marks; or\n\nf) Requiring indemnification of licensors and authors of that\nmaterial by anyone who conveys the material (or modified versions of\nit) with contractual assumptions of liability to the recipient, for\nany liability that these contractual assumptions directly impose on\nthose licensors and authors.\n

All other non-permissive additional terms are considered \"further restrictions\" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.

If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.

Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.

8. Termination.

You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).

However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.

Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.

Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.

9. Acceptance Not Required for Having Copies.

You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.

10. Automatic Licensing of Downstream Recipients.

Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.

An \"entity transaction\" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.

You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.

11. Patents.

A \"contributor\" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's \"contributor version\".

A contributor's \"essential patent claims\" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, \"control\" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.

Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.

In the following three paragraphs, a \"patent license\" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To \"grant\" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.

If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. \"Knowingly relying\" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.

If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.

A patent license is \"discriminatory\" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.

Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.

12. No Surrender of Others' Freedom.

If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.

13. Remote Network Interaction; Use with the GNU General Public License.

Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph.

Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License.

14. Revised Versions of this License.

The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License \"or any later version\" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation.

If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.

Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.

15. Disclaimer of Warranty.

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

16. Limitation of Liability.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

17. Interpretation of Sections 15 and 16.

If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.

                 END OF TERMS AND CONDITIONS\n\n        How to Apply These Terms to Your New Programs\n

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the \"copyright\" line and a pointer to where the full notice is found.

<one line to give the program's name and a brief idea of what it does.>\nCopyright (C) <year>  <name of author>\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published\nby the Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see <https://www.gnu.org/licenses/>.\n

Also add information on how to contact you by electronic and paper mail.

If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a \"Source\" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements.

You should also get your employer (if you work as a programmer) or school, if any, to sign a \"copyright disclaimer\" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see https://www.gnu.org/licenses/.

"},{"location":"salesforce-ai-setup/","title":"Sfdx-hardis AI assistant setup","text":""},{"location":"salesforce-ai-setup/#setup-ai-for-sfdx-hardis","title":"Setup AI for sfdx-hardis","text":"

You need to define at least env variable OPENAI_API_KEY and make it available to your CI/CD workflow.

To get an OpenAi API key, create an OpenAi Platform account.

Variable Description Default OPENAI_API_KEY Your openai account API key OPENAI_MODEL OpenAi model used to perform prompts (see models list) gpt-4o AI_MAXIMUM_CALL_NUMBER Maximum allowed number of calls to OpenAi API during a single sfdx-hardis command 10"},{"location":"salesforce-ci-cd-clone-repository/","title":"Clone git repository of a Salesforce project","text":"
  • Pre-requisites
  • Clone the repository
    • From the Git server UI
    • From Visual Studio Code
"},{"location":"salesforce-ci-cd-clone-repository/#pre-requisites","title":"Pre-requisites","text":"

You need to access to a Git repository and the url of the repository to clone.

The release manager of the project can provide it.

It looks like the following: https://github.com/trailheadapps/dreamhouse-lwc.git

"},{"location":"salesforce-ci-cd-clone-repository/#clone-the-repository","title":"Clone the repository","text":"

If you don't have a folder for your git repositories, create a C:\\git folder and use it as destination for your git clones !

"},{"location":"salesforce-ci-cd-clone-repository/#from-the-git-server-ui","title":"From the Git server UI","text":"

Git providers UIs sometimes have a button Clone -> Open In VsCode

If you can use it, use it :)

"},{"location":"salesforce-ci-cd-clone-repository/#gitlab","title":"Gitlab","text":"

If later you are prompted for username and password, you might need to create a Personal Access Token (video tuto here) and use it as password.

If later, it prompts several times the same password in VsCode, run the following command line

git config --global credential.helper store

"},{"location":"salesforce-ci-cd-clone-repository/#azure","title":"Azure","text":""},{"location":"salesforce-ci-cd-clone-repository/#from-visual-studio-code","title":"From Visual Studio Code","text":"
  • In Visual Studio Code, hit CTRL+Shirt+P then look for command Git clone then click to select it.
  • Paste the url of your git repository then hit ENTER
    • If you are asked for a directory and you don't have one yet, create an empty directory at the root of your hard drive, and select it (examples: C:/git or D:/git )
  • Click on the Open notification in VsCode
  • You are now ready to create a new task !
"},{"location":"salesforce-ci-cd-config-cleaning/","title":"Configure a Salesforce CI/CD Cleaning using sfdx-hardis","text":"
  • Why cleaning sources ?
  • Dashboards
  • Destructive Changes
  • List Views Mine
  • Minimize Profiles
  • System.debug
  • Named metadatas
    • Case Entitlement
    • DataDotCom
    • Local Field
    • Product Request
"},{"location":"salesforce-ci-cd-config-cleaning/#why-cleaning-sources","title":"Why cleaning sources ?","text":"

Salesforce CI/CD Pipelines does not natively work without many manual operations to update the XML... so the deployments passes !

sfdx-hardis provides a set of commands to automate those boring XML updates that can be called every time a user prepares a merge request using command sf hardis:work:save

Here is the list of available automated cleanings, that can also be called manually using command

Example of cleaning config in a .sfdx-hardis.yml config file:

autoCleanTypes:\n  - destructivechanges\n  - datadotcom\n  - minimizeProfiles\n  - listViewsMine\n
"},{"location":"salesforce-ci-cd-config-cleaning/#dashboards","title":"Dashboards","text":"

Property: dashboards

Removes hardcoded user ids from Dashboards

"},{"location":"salesforce-ci-cd-config-cleaning/#destructive-changes","title":"Destructive Changes","text":"

Property: destructivechanges

Any file corresponding to an element existing in manifest/destructiveChanges.xml is deleted.

"},{"location":"salesforce-ci-cd-config-cleaning/#list-views-mine","title":"List Views Mine","text":"

Property: listViewsMine

List views with scope Mine can not be deployed.

As a workaround, scope is set back to Everything in XML, but the list view reference is kept in a property listViewsToSetToMine in .sfdx-hardis.yml, and after deployment, manual clicks are simulated to set back their scope to Mine !

"},{"location":"salesforce-ci-cd-config-cleaning/#minimize-profiles","title":"Minimize Profiles","text":"

Property: minimizeProfiles

It is a bad practice to define on Profiles elements that can be defined on Permission Sets.

Salesforce will deprecate such capability in Spring 26.

Don't wait for that, and use minimizeProfiles cleaning to automatically remove from Profiles any permission that exists on a Permission Set !

The following XML tags are removed automatically:

  • classAccesses
  • customMetadataTypeAccesses
  • externalDataSourceAccesses
  • fieldPermissions
  • objectPermissions
  • pageAccesses
  • userPermissions (except on Admin Profile)

You can override this list by defining a property minimizeProfilesNodesToRemove in your .sfdx-hardis.yml config file.

__

"},{"location":"salesforce-ci-cd-config-cleaning/#systemdebug","title":"System.debug","text":"

Property: systemDebug

System.debug are useless, as explained in this article

Comments automatically all System.debug in the code to enhance performances.

"},{"location":"salesforce-ci-cd-config-cleaning/#named-metadatas","title":"Named metadatas","text":"

Cleaning can remove files related to named elements.

"},{"location":"salesforce-ci-cd-config-cleaning/#case-entitlement","title":"Case Entitlement","text":"

Property: caseentitlement

Removes all Case Entitlement related fields, like Case.EntitlementId and Case.MilestoneStatus

"},{"location":"salesforce-ci-cd-config-cleaning/#datadotcom","title":"DataDotCom","text":"

Property: datadotcom

Removes all Case Data.com related fields, like Account.DandbCompanyId and Account.Jigsaw

"},{"location":"salesforce-ci-cd-config-cleaning/#local-field","title":"Local Field","text":"

Property: localfields

Removes all Local fields, like Account.NameLocal and Lead.CompanyLocal

"},{"location":"salesforce-ci-cd-config-cleaning/#product-request","title":"Product Request","text":"

Property: productrequest

Removes all Local fields, like ProductRequest.ShipToAddress and ProductRequest.ShipmentType

"},{"location":"salesforce-ci-cd-config-delta-deployment/","title":"Configure delta deployments on a Salesforce CI/CD Project","text":"
  • Delta deployments
    • Full mode
    • Delta mode
  • Configuration
    • Base
    • Advanced
"},{"location":"salesforce-ci-cd-config-delta-deployment/#delta-deployments","title":"Delta deployments","text":""},{"location":"salesforce-ci-cd-config-delta-deployment/#full-mode","title":"Full mode","text":"

By default, all deployments job (check deploy & process deploy) deploy the full content of the package.xml minus what is matching package-no-overwrite.xml (formerly packageDeployOnce.xml)

This is the safest way to deploy at each level

  • major to major
  • minor to major
"},{"location":"salesforce-ci-cd-config-delta-deployment/#delta-mode","title":"Delta mode","text":"

In order to improve performances on project with large metadata base, you can activate delta deployments for Pull Request/Merge Requests from a minor branch (examples: feature/xxx, debug/xxx) to a major branch (ex: integration, uat, preprod, production: sfdx-hardis will deploy only updated metadatas in the Pull Request / Merge Request.

Merge Requests / Pull Request between major branches (ex: uat to preprod) remains in full deployment mode, to avoid issues with configuration which would have been done directly in the orgs (whereas it shouldn't be, except for Reports, Dashboards and a few metadata types)

Examples:

  • features/config/my-work to integration will be DELTA DEPLOYMENT
  • integration to uat will be FULL DEPLOYMENT
  • hotfixes/fix-stuff to preprod will be DELTA DEPLOYMENT
  • preprod to production will be FULL DEPLOYMENT

\ud83d\udca1 If you want to force the use of full deployment for a PR/MR on a delta project, add \"nodelta\" in your latest commit title or text.

"},{"location":"salesforce-ci-cd-config-delta-deployment/#configuration","title":"Configuration","text":""},{"location":"salesforce-ci-cd-config-delta-deployment/#base","title":"Base","text":"

To activate delta deployments,you can:

  • define useDeltaDeployment: true in config/.sfdx-hardis.yml
  • define env variable USE_DELTA_DEPLOYMENT=true

In case of temporary deactivation of delta deployments, you can set variable DISABLE_DELTA_DEPLOYMENT=true, it has priority on other configurations.

\ud83d\udca1If your sfdx-hardis installation is from before 4.10.0, you might need to update your CI/CD workflows

Check updated versions in sfdx-hardis sources

It is recommended to use opinionated default sfdx-hardis delta deployment configuration, but if you want to tweak the config you can use the following variables:

"},{"location":"salesforce-ci-cd-config-delta-deployment/#advanced","title":"Advanced","text":"
  • USE_DELTA_DEPLOYMENT_AFTER_MERGE
    • By default, after a merge sfdx-hardis will try to use QuickDeploy. If not available, it will perform a full deployment. If you want to use a delta deployment anyway, define USE_DELTA_DEPLOYMENT_AFTER_MERGE=true
  • ALWAYS_ENABLE_DELTA_DEPLOYMENT
    • By default, delta deployment is allowed only from minor to major branches. You can force it for PR/MRs between major branches by defining variable ALWAYS_ENABLE_DELTA_DEPLOYMENT=true
"},{"location":"salesforce-ci-cd-config-home/","title":"Configure a Salesforce CI/CD Project using sfdx-hardis","text":"
  • package.xml
    • Overwrite Management
    • Delta deployments
  • destructiveChanges.xml
  • Automated sources cleaning
  • Source retrieve issues
  • All configuration properties
"},{"location":"salesforce-ci-cd-config-home/#packagexml","title":"package.xml","text":"

A Salesforce CI/CD repository contains a file manifest/package.xml.

  • It contains all metadatas that will be deployed by the CI server.
  • It is automatically updated when preparing merge requests by command hardis:work:save
"},{"location":"salesforce-ci-cd-config-home/#overwrite-management","title":"Overwrite Management","text":"
  • It is highly recommended to configure overwrite management, to avoid to overwrite metadatas that are maintained directly in production on purpose

    • Dashboards
    • Reports
    • Remote site settings
    • Named credentials
    • ...

    See Overwrite management configuration documentation

"},{"location":"salesforce-ci-cd-config-home/#delta-deployments","title":"Delta deployments","text":"
  • You can also use delta deployments if your project is big and you have performances issues.
"},{"location":"salesforce-ci-cd-config-home/#source-retrieve-issues","title":"Source retrieve issues","text":"

Handle cases when force:source:pull does not retrieve every updated source.

See how to force the retrieve of named sources

"},{"location":"salesforce-ci-cd-config-home/#destructivechangesxml","title":"destructiveChanges.xml","text":"

A Salesforce CI/CD repository contains a file manifest/destructiveChanges.xml.

  • It contains all metadatas that will be deleted by the CI server.
  • It is automatically updated when preparing merge requests by command hardis:work:save
"},{"location":"salesforce-ci-cd-config-home/#automated-sources-cleaning","title":"Automated sources cleaning","text":"

You can configure automated cleaning of sources before creating merge requests, using command hardis:work:save

Those cleanings can be:

  • Deletion of sources existing in destructiveChanges.xml
  • Remove from Profiles elements that are existing in Permission Sets, like Objects access configuration.
  • etc ...

    See Overwrite cleaning configuration documentation

"},{"location":"salesforce-ci-cd-config-home/#all-configuration-properties","title":"All configuration properties","text":"

.sfdx-hardis.yml allows to make your project highly configuration. Have a look at its list of configuration properties !

"},{"location":"salesforce-ci-cd-config-overwrite/","title":"Configure overwrite management on a Salesforce CI/CD Project","text":"
  • package-no-overwrite.xml
    • Definition
    • Example
  • packageDeployOnChange.xml
"},{"location":"salesforce-ci-cd-config-overwrite/#package-no-overwritexml","title":"package-no-overwrite.xml","text":""},{"location":"salesforce-ci-cd-config-overwrite/#definition","title":"Definition","text":"

For different reasons, many metadatas are maintained manually, using production Salesforce org Setup

To avoid to overwrite manual updates in setup, you must define at least a manifest/package-no-overwrite.xml file. (formerly named packageDeployOnce.xml)

The rule is simple and must be learnt by heart:

Every item which is existing in package.xml AND matching package-no-overwrite.xml AND existing in the target deployment org will NOT be deployed.

This means that an item matching package-no-overwrite.xml will be deployed the first time, but never overwritten, so has to be manually maintained in org using Setup.

  • This file must be located at manifest/package-no-overwrite.xml (formerly packageDeployOnce.xml)
  • It has the same format than a package.xml, but must be written manually
  • It can contain named items, or wildcards *
  • Theoretically, any metadata can be added in package-no-overwrite.xml, but here are the most commonly present:
    • Connected apps
    • Dashboards
    • Named Credentials
    • Profiles
    • Remote Site Settings
    • Reports
    • SAML SSO Configuration
    • Wave items (CRM Analytics)
"},{"location":"salesforce-ci-cd-config-overwrite/#example","title":"Example","text":"
<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Package xmlns=\"http://soap.sforce.com/2006/04/metadata\">\n  <!-- Approval processes can contain reference to usernames -->\n  <types>\n      <members>*</members>\n      <name>ApprovalProcess</name>\n  </types>\n  <!-- Connected apps contain org unique auth info so must never be overwritten -->\n  <types>\n      <members>*</members>\n      <name>ConnectedApp</name>\n  </types>\n  <types>\n    <!-- Apps that contain hardcoded dashboard its must be managed directly in production -->\n    <members>DeclareWork</members>\n    <members>Facturation</members>\n    <members>SomeApp2</members>\n    <name>CustomApplication</name>\n  </types>\n  <types>\n    <!-- Once a dashboard is published, it is always managed directly in production -->\n    <members>*</members>\n    <name>Dashboard</name>\n  </types>\n  <types>\n    <!-- flexipages that contain Dashboard ids -->\n    <members>Accueil_administrateur</members> \n    <members>Accueil_administratif</members>\n    <members>Accueil_Commerciaux</members>\n    <members>Accueil_Direction</members>\n    <members>Accueil_Recrutement</members>\n    <name>Flexipage</name>\n  </types> \n  <types>\n    <!-- Name Credentials can contain auth info that are different between dev, uat, preprod and prod: let's not overwrite them ! -->\n    <members>*</members>\n    <name>NamedCredential</name>\n  </types>  \n  <types>\n    <!-- Use permission sets -->\n    <members>*</members>\n    <name>Profile</name>\n  </types>\n  <types>\n    <!-- Remote site settings can be different between dev, uat, preprod and prod: let's not overwrite them ! -->\n    <members>*</members>\n    <name>RemoteSiteSetting</name>\n  </types>  \n  <types>\n    <!-- Reports are maintained directly in production -->\n    <members>*</members>\n    <name>Report</name>\n  </types>\n    <!-- SSO Config must be performed directly in org setup -->  \n  <types>\n      <members>*</members>\n      <name>SamlSsoConfig</name>\n  </types>\n  <!-- Wave items in case you want to manage them directly in production -->\n  <types>\n    <members>*</members>\n    <name>WaveApplication</name>\n  </types>\n  <types>\n    <members>*</members>\n    <name>WaveDashboard</name>\n  </types>\n  <types>\n    <members>*</members>\n    <name>WaveDataflow</name>\n  </types>\n  <types>\n    <members>*</members>\n    <name>WaveDataset</name>\n  </types>\n  <types>\n    <members>*</members>\n    <name>WaveRecipe</name>\n  </types>\n  <types>\n    <members>*</members>\n    <name>WaveXmd</name>\n  </types>\n  <version>53.0</version>\n</Package>\n
"},{"location":"salesforce-ci-cd-config-overwrite/#packagedeployonchangexml","title":"packageDeployOnChange.xml","text":"

packageDeployOnChange.xml is slightly different from package-no-overwrite.xml: it will deploy only if the target metadata XML is different from the source metadata XML that we want to deploy

  • This file must be located at manifest/packageDeployOnChange.xml
  • It can contain named items, or wildcards *
  • Is has much lower performances than package-no-overwrite.xml, so must be used wisely
  • Theoretically, any metadata can be added in packageDeployOnChange.xml, but here are the most commonly present:
    • Sharing Rules
    • Sharing Owner Rules
"},{"location":"salesforce-ci-cd-conga/","title":"Configure overwrite management on a Salesforce CI/CD Project","text":""},{"location":"salesforce-ci-cd-conga/#conga-deployments","title":"Conga deployments","text":"

It's easy to handle the deployment of Conga Composer configuration with sfdx-hardis.

Please see how in the following article.

"},{"location":"salesforce-ci-cd-create-new-task/","title":"Create new task on a Salesforce DX project","text":"
  • Use cases
  • Sandbox or scratch org ?
  • Source-tracked sandbox mode
    • Pre-requisites (sandbox)
    • Start new task on sandbox
      • Select sandbox
      • Update your sandbox ?
      • Work !
  • Scratch Org mode
    • Pre-requisites (scratch org)
    • Start new task on scratch org
"},{"location":"salesforce-ci-cd-create-new-task/#use-cases","title":"Use cases","text":"

You use this command when you want to :

  • Create a dedicated new branch
  • Create a scratch org linked to the branch OR assign a dedicated sandbox to the newly created branch
"},{"location":"salesforce-ci-cd-create-new-task/#sandbox-or-scratch-org","title":"Sandbox or scratch org ?","text":"

With SFDX, usually each member of the teams has its own sandbox or scratch org to work on it.

The release manager of the project can tell you if you work with scratch orgs or source-tracked sandboxes, and which sandbox to use if you are in sandbox mode.

"},{"location":"salesforce-ci-cd-create-new-task/#source-tracked-sandbox-mode","title":"Source-tracked sandbox mode","text":""},{"location":"salesforce-ci-cd-create-new-task/#pre-requisites-sandbox","title":"Pre-requisites (sandbox)","text":"

You need credentials to login on the source-tracked sandbox you'll work with. It can be:

  • An existing source-tracked sandbox
    • Existing source-tracked sandboxes must be refreshed from time to time to avoid too many conflicts, discuss with your Release Manager !
    • Release managers: When you create or refresh a sandbox, you can easily activate invalid users with a few clicks
  • A new source-tracked sandbox that you can create from production org

It is recommended to create sandbox from the org that is related to the target git branch.

"},{"location":"salesforce-ci-cd-create-new-task/#start-new-task-on-sandbox","title":"Start new task on sandbox","text":""},{"location":"salesforce-ci-cd-create-new-task/#select-sandbox","title":"Select sandbox","text":"
  • Open VsCode SFDX Hardis extension by clicking on in VsCode left bar (loading can task several seconds)
  • Click on
  • Answer the questions then select Sandbox when prompted
    • If the sandbox is not proposed in the list, select the option to authenticate to your desired sandbox
"},{"location":"salesforce-ci-cd-create-new-task/#update-your-sandbox","title":"Update your sandbox ?","text":"
  • When prompted if you want to update your sandbox:
    • Select yes only if you have NO pending work in your sandbox that you'll want to publish later
      • If the update script fails, you can manually deploy single metadatas using Right click -> Deploy to org (see screenshot below)
    • Otherwise, select no

Example of manual deploy of a metadata that you think could have been updated in parent branch, after an Update sandbox failure

"},{"location":"salesforce-ci-cd-create-new-task/#work","title":"Work","text":"
  • At the end of the script execution:

    • If you want to reset the sandbox tracking (meaning you don't care about the previous updates in your sandbox), you can click on command
    • Click on and you can start working in it :)

Under the hood

See details in hardis:work:new command documentation

"},{"location":"salesforce-ci-cd-create-new-task/#scratch-org-mode","title":"Scratch Org mode","text":""},{"location":"salesforce-ci-cd-create-new-task/#pre-requisites-scratch-org","title":"Pre-requisites (scratch org)","text":"

You need the credentials to login on the Dev Hub Org (usually the production environment)

"},{"location":"salesforce-ci-cd-create-new-task/#start-new-task-on-scratch-org","title":"Start new task on scratch org","text":"
  • Open VsCode SFDX Hardis extension by clicking on in VsCode left bar
  • Click on
  • Answer the questions then select Scratch Org when prompted
    • If the sandbox is not proposed in the list, select the option to authenticate to your desired sandbox
  • Wait for the sandbox creation script to be completed, and you can start working in it :)
    • If you see errors while creating the sandbox, request support from the project release manager

Under the hood

See details in hardis:work:new command documentation

"},{"location":"salesforce-ci-cd-deploy-major-branches/","title":"Deploy to major branches and orgs with Salesforce CI/CD","text":"
  • Minor and Major branches
  • Merge requests between major branches
"},{"location":"salesforce-ci-cd-deploy-major-branches/#minor-and-major-branches","title":"Minor and Major branches","text":"

Minor branches are individual git branches that do not have a CI/CD associated org

Major branches are git branches that have a CI/CD associated org, and each new commit in a major branch automatically triggers a deployment to the associated org.

Examples:

  • Minor to major: When a merge request from dev_nico to \u00ecntegration (1) is validated and merged, a new state (commit) is detected in branch integration, so CI server automatically deploys to associated Salesforce org Integration (2)
  • Major to Major: When a merge request from integration to uat (3) is validated and merged, a new state (commit) is detected in branch uat, so CI server automatically deploys to associated Salesforce org UAT (4)
  • Major to Major: When a merge request from preprod to production (5) is validated and merged, a new state (commit) is detected in branch production, so CI server automatically deploys to associated Salesforce org Production (6)
"},{"location":"salesforce-ci-cd-deploy-major-branches/#merge-requests-between-major-branches","title":"Merge requests between major branches","text":"
  • Create a New Merge request
    • Set a meaningful title, like MAJOR: recette to uat or MAJOR: uat to production
    • Make sure that Delete source after merge and Squash commits are UNCHECKED
  • Click on Submit merge request
  • Controlling jobs are automatically launched, and should pass as merge requests from minor branches has been in success
    • If jobs fail, it means that you need to perform manual actions in target org, like activating features or manually rename elements if metadatas API Names has been renamed (which is a bad practice but happens)
  • Once all jobs are in success, merge the merge request
    • It will automatically trigger the deployment to the associated Salesforce org
"},{"location":"salesforce-ci-cd-handle-merge-request-results/","title":"Handle Merge Request Results","text":"
  • Conflicts detection
  • Deployment simulation
  • Quality gate
"},{"location":"salesforce-ci-cd-handle-merge-request-results/#conflicts-detection","title":"Conflicts detection","text":"

If you are about to overwrite the work of one of your colleagues, a conflicts message will appear.

  • If you are trained with git, you can merge conflicts by merging the target branch in your own branch
  • Otherwise, call your release manager !
"},{"location":"salesforce-ci-cd-handle-merge-request-results/#deployment-simulation","title":"Deployment simulation","text":"

When you create a Merge Request to a major git branch, for example integration, sfdx-hardis will simulate a deployment to the related major Salesforce org, for example Integration org.

It will also run Apex test classes and Apex code coverage.

The result will be displayed in a message on the Merge Request UI

If you see errors, please check Solve deployment errors documentation

"},{"location":"salesforce-ci-cd-handle-merge-request-results/#quality-gate","title":"Quality gate","text":"

Any Merge Request will trigger a technical quality gate, that will check for:

  • Apex best practices using PMD
  • LWC best practices using eslint
  • Security issues
  • Excessive copy-pastes

The result will be displayed in a message on the Merge Request UI

If you see errors, please check Solve MegaLinter errors documentation

"},{"location":"salesforce-ci-cd-home/","title":"Salesforce CI/CD with sfdx-hardis","text":"
  • Introduction
  • Use sfdx-hardis CI/CD
  • Release Management
  • Setup sfdx-hardis CI/CD
"},{"location":"salesforce-ci-cd-home/#introduction","title":"Introduction","text":"

There are many ways to do DevOps with Salesforce, each of them have their advantages and inconveniences, like showed in the following comparison table.

You can setup and use a full CI/CD pipeline for your Salesforce projects using sfdx-hardis, with advanced features:

  • Admins are autonomous to build their pull requests with clicks on VsCode Extension, no command lines
  • Delta Deployments: Improve performances by deploying only updated metadatas
  • Overwrite Management: Define which metadatas will never be overwritten if they are already existing in the target org of a deployment
  • Smart Apex Test Runs: If your Pull Request to a sandbox can not break Apex Tests, just don't run them to improve performances.
  • Automated sources cleaning: Clean profiles from attributes existing on permission sets, clean flow positions...
  • Integration with Messaging platforms: Receive detailed deployment notifications on Slack, Microsoft Teams and Emails
  • Integration with ticketing systems: JIRA, Azure Boards, or any other tool

We provide ready to use CI/CD pipeline workflows for the following Git platforms, with results of Deployment simulation jobs as comments on Pull Requests:

  • Gitlab
  • Azure
  • Github
  • BitBucket

Pipelines can easily be adapted to other platforms like Jenkins or TeamCity

If you speak fluently git, sfdx & DevOps, you can be fully autonomous to setup and use Salesforce CI/CD, otherwise you can contact us at Cloudity (or your favorite Salesforce integrator) and we'll be glad to assist you :)

As everything is open-source, there is no license costs !

See presentation of sfdx-hardis at Dreamforce !

See Slides of Dreamforce 23 session

Here is an advanced example of a Salesforce CI/CD Pipeline that you can easily define using sfdx-hardis. You can define much simpler branch/orgs models, to manage only RUN operations.

See detailed article on SalesforceDevOps.net

See quick demo video for a Contributor

"},{"location":"salesforce-ci-cd-home/#use-sfdx-hardis-cicd","title":"Use sfdx-hardis CI/CD","text":"

Please read Contributor Guide to know how to work on CI/CD projects, as an Business consultant, a Developer or a Release Manager

"},{"location":"salesforce-ci-cd-home/#release-management","title":"Release Management","text":"

Please read Release Manager Guide to know how to be a release manager on Salesforce CI/CD project.

"},{"location":"salesforce-ci-cd-home/#setup-sfdx-hardis-cicd","title":"Setup sfdx-hardis CI/CD","text":"

Please read Setup Guide to know how to initialize and maintain a Salesforce CI/CD project.

"},{"location":"salesforce-ci-cd-hotfixes/","title":"Handle deployment of hotfix in production with Salesforce CI/CD","text":""},{"location":"salesforce-ci-cd-hotfixes/#build-run","title":"BUILD & RUN","text":"

Except for projects in maintenance that contain RUN only, a project is separated into 2 sections:

  • the RUN stream: Fast cycle, to often deploy minor changes and fixes
  • the BUILD stream: Project cycle, to build more advanced features and enhancements, that require User Acceptance Testing

"},{"location":"salesforce-ci-cd-hotfixes/#the-build","title":"THE BUILD","text":"

This is the layer where you prepare the next major or minor version.

Such new features will go through integration level, then uat level where they will be qualified and validated by business users.

When the User Acceptance Test will be validated in uat org, then uat can be merged into preprod, and just after minimal tests (mostly technical), preprod will soon be merged into production.

Is it important that major features or enhancements are not tested directly at preprod level, because while the next version is being validated in preprod, it is not possible for the RUN to deploy anything into production.

"},{"location":"salesforce-ci-cd-hotfixes/#the-run","title":"THE RUN","text":"

Daily maintenance of the production Salesforce org must be very reactive, the RUN level will allow you to often deploy patch versions.

As we usually can not wait for the next minor or major version to be deployed in production, projects need a way to quickly deploy hot fixes into production. That layer is called the RUN, and is exclusively about preprod and main branches.

To summarize, you will publish at RUN level, but also at BUILD level, so when the BUILD will be merged in the RUN, there will be no overwrite triggering regressions.

The hotfix process is the following:

Note: in this example, we merge directly in preprod, but in more advanced organizations we can define a branch/org uat_run as intermediate layer before merging to preprod

  • IMPLEMENT HOTFIX (1)

    • Create new task with preprod as target when prompted, named my-very-hot-hotfix for example
    • Work on a dev sandbox that has been cloned from production
  • DEPLOYMENT IN RUN LAYER (2)

    • Create Pull Request from my-very-hot-hotfix to preprod & merge it after controls (do not select \u201cdelete after merge\u201d )
    • Create Pull request from preprod to main
    • Merge preprod to main after control checks are green.
  • RETROFIT IN BUILD LAYER (3)

    • Create a sub-branch to integration, named retrofit-from-run for example
    • Using Git IDE, manually merge main (or preprod) branch into retrofit-from-run
    • If there are git conflicts, solve them before committing
    • Create Pull Request from retrofit-from-run to integration
    • Merge the Pull Request into integration: your retrofit from the RUN to the BUILD is over :)
      • You might refresh dev sandboxes if your retrofits have lots of impacts
"},{"location":"salesforce-ci-cd-merge-request-gitlab/","title":"Create a merge request using Gitlab","text":""},{"location":"salesforce-ci-cd-merge-request-gitlab/#create-a-merge-request-using-gitlab","title":"Create a merge request using Gitlab","text":"
  • Go in your online repository in your web browser (example: https://gitlab.com/trailheadapps/dreamhouse-lwc)
  • Go to menu Merge Requests
  • Create a New Merge request
  • Click on Submit merge request
  • Controlling jobs are automatically launched, you can now ask your release manager to validate the merge request
    • If you are a developer, (or even a business consultant depending on the project organization), you may have the responsibility to make sure than controlling jobs are valid (check-deploy job and code-quality job in success) and eventually fix the errors (See Handle merge requests errors)
  • If you need to add additional updates to an existing merge requests, you just this to follow again this guide from the beginning, except the part \"Create a merge request\". Any new commit pushed on a branch where there is already a merge request will trigger again the control jobs.
"},{"location":"salesforce-ci-cd-packaging/","title":"Generate packages and package versions","text":""},{"location":"salesforce-ci-cd-packaging/#pre-requisites","title":"Pre-requisites","text":"

sfdx-hardis menus allow to create new packages and new package versions, but to do that you need some pre-requisites.

  • In order to generate packages, you first need a Dev Hub to link them.

    • Instructions in Salesforce Documentation
  • If you need to use a namespace with a package (managed or unmanaged), you also need to link you Dev Hub and a dev org where you will create the namespace.

    • Instructions in Salesforce Documentation
  • Then you need a sfdx-hardis flavored sfdx project, that you can create with sf hardis:project:create, using scratch orgs only option.
  • Last, create your package folder (ex: my-package) at the root of the repository, following the same structure than force-app: it will contain your package content.
"},{"location":"salesforce-ci-cd-packaging/#new-package","title":"New package","text":"

Use sfdx-hardis menu Packaging -> Create a new package and follow instructions (select the folder that you just created, don't use force-app)

"},{"location":"salesforce-ci-cd-packaging/#new-package-version","title":"New package version","text":""},{"location":"salesforce-ci-cd-packaging/#git-branch","title":"Git branch","text":"

Create a git sub-branch of your packaging branch (for example pkg/release-v0.1.0)

"},{"location":"salesforce-ci-cd-packaging/#increment-package-version","title":"Increment package version","text":"

Before being able to generate a new package version, you need to increment the package version in sfdx-project.json.

{\n  \"packageDirectories\": [\n    {\n      \"path\": \"package-astran\",\n      \"default\": true,\n      \"package\": \"Astran\",\n      \"versionName\": \"ver 0.1\",                         # Change version name here to match the incremented package version\n      \"versionNumber\": \"0.1.0.NEXT\",                    # Increment version here (Respect SEMVER or you will have errors)\n      \"versionDescription\": \"Astran for Salesforce\"\n    },\n    {\n      \"path\": \"scratch\",\n      \"default\": false\n    }\n  ],\n  \"name\": \"astran\",\n  \"namespace\": \"Astran\",\n  \"sfdcLoginUrl\": \"https://my-devhub-org.salesforce.com\",\n  \"sourceApiVersion\": \"57.0\"\n}\n
"},{"location":"salesforce-ci-cd-packaging/#run-create-package-version-command","title":"Run create package version command","text":"

Run sfdx-hardis command Packaging -> Create new package version

Select the package you want to create a version, and input an installation if necessary (otherwise let it blank)

After some time, the new package version will be generated, and you will be able to find its ID in your sfdx-project.json

{\n    ...\n      \"packageAliases\": {\n        \"Astran\": \"0Ho7S0123010wZWSAU\",\n        \"Astran@0.1.0-1\": \"04t7S000000gYxPQAF\",\n        \"Astran@0.1.0-2\": \"04t7S000000gYm1QAE\",\n        \"Astran@0.1.0-3\": \"04t7S000000gYp7WAG\",\n}\n

If you have issues, it might be because you incremented the version as a patch whereas the updates with the previous version require at least a minor version.

For example, 1.1.4.NEXT can fail, and 1.2.0.NEXT will pass

"},{"location":"salesforce-ci-cd-packaging/#test-the-beta-version","title":"Test the beta version","text":"

(optional but recommended)

The latest entry is the one you can use to install the beta package version (every created package version is a beta by default)

Example of URL to append at the end of your org domain name: /packaging/installPackage.apexp?p0=04t7S000000gYp7QAG

Install the beta package in a dummy sandbox to check that its content is ok for you

"},{"location":"salesforce-ci-cd-packaging/#pull-request-to-packaging-branch","title":"Pull request to packaging branch","text":"

Once you decide the package is ok for you, make a Pull Request to the packaging branch (or main branch, depending on your project config)

"},{"location":"salesforce-ci-cd-packaging/#promote-the-beta","title":"Promote the beta","text":"

Once you merged your PR in packaging branch (after checking the control jobs are green), you can promote the package.

WARNING: Promoting a package is a sensitive operation, because it declares it as production-ready, then you can not remove metadatas from it, and you must respect ascending compatibility to generate new package versions !

To promote a package version, run the following command

sf hardis:package:version:promote

Example: sf hardis:package:version:promote

Note: When later you will create a new scratch org in a new development branch, if you have issues, just increment again the versionNumber in sfdx-project.json

"},{"location":"salesforce-ci-cd-packaging/#create-version-git-tag","title":"Create version git tag","text":"

Once you promoted a package, create a git tag with the version id on the commit corresponding to your merged Pull Request

Example: v1.1.0

Push the git tag to origin

"},{"location":"salesforce-ci-cd-publish-task/","title":"Publish a task on a Salesforce CI/CD project","text":"
  • Commit your updates
    • Retrieve metadatas
    • Stage and commit
  • Prepare merge request
  • Create merge request
    • Using Gitlab
    • Using Github
    • Using Azure
  • Check merge request results
"},{"location":"salesforce-ci-cd-publish-task/#commit-your-updates","title":"Commit your updates","text":"

The following video shows how to perform theses operations

"},{"location":"salesforce-ci-cd-publish-task/#retrieve-metadatas","title":"Retrieve metadatas","text":"

If you made updates on your org that you have not pulled yet, Use command to pull your latest updates in local files

If you updated config elements that you do not see in your local files, you may discuss with your release manager to automate force retrieve metadatas

"},{"location":"salesforce-ci-cd-publish-task/#alternative-use-org-browser","title":"Alternative: Use Org Browser","text":"

You can also use Salesforce extension Org Browser to manually browse and retrieve specific metadatas

"},{"location":"salesforce-ci-cd-publish-task/#alternative-use-contextual-menu","title":"Alternative: Use contextual menu","text":"

If Org Browser does not see items that you want to retrieve, like list views, you can right click on any listViews folder and use command SFDX: Retrieve source from org

"},{"location":"salesforce-ci-cd-publish-task/#alternative-use-menu-select-and-retrieve","title":"Alternative: Use menu \"Select and retrieve\"","text":"

If it is not possible to use pull configuration, you may retrieve metadatas using (but it will retrieve locally many files and it will be harder to select the ones you really need, select carefully the items that you stage and commit)

"},{"location":"salesforce-ci-cd-publish-task/#stage-and-commit","title":"Stage and commit","text":"

In VsCode Git extension, stage and commit created, updated and deleted files that you want to publish

  • By selecting the metadata files you can see the differences with the previous versions, to know if you want to publish or not an updated file
  • Never use Stage all function
  • If you see standard items like standard fields that do not contain customizations, do not commit them
  • Important: If you think that your sandbox may not be up to date according to elements published by your colleagues, look closely at the diff on those items, and stage only the updates that you want to publish

"},{"location":"salesforce-ci-cd-publish-task/#prepare-merge-request","title":"Prepare merge request","text":"
  • Once your commit is completed, run command to prepare your merge request.
  • As you committed your files like explained in the previous section, select option when prompted.
  • Wait for the script to complete, and select Push commit to server when prompted

Under the hood

The script performs the following operations:

  • Update manifest/package.xml automatically according to the committed updates
  • Clean XML of metadatas according to .sfdx-hardis.yml config property autoCleanTypes and autoRemoveUserPermissions
  • New git commit with automated updates
  • Git push commit to git server

More details in hardis:work:save command documentation

"},{"location":"salesforce-ci-cd-publish-task/#create-merge-request","title":"Create merge request","text":"

It is now time to create your merge request to technically publish your updates at the upper level !

Depending on the CI platform you use, follow the related guide.

If you are publishing to a RUN branch (ex: preprod), AND the project also has a BUILD branch (ex: integration), you need to notify the release manager He/she will have to retrofit your updates once published

If you are working with a ticketing system like JIRA, make sure to add the full url of the tickets in the MR/PR description, so it will help for the release management. For example, use https://sfdx-hardis.atlassian.net/browse/CLOUDITY-4 , not CLOUDITY-4

"},{"location":"salesforce-ci-cd-publish-task/#using-gitlab","title":"Using Gitlab","text":"

See Create a merge request using Gitlab

"},{"location":"salesforce-ci-cd-publish-task/#using-azure","title":"Using Azure","text":"

See Create a merge request using Azure

"},{"location":"salesforce-ci-cd-publish-task/#using-github","title":"Using GitHub","text":"

See Create a merge request using Github

"},{"location":"salesforce-ci-cd-publish-task/#check-merge-request-results","title":"Check merge request results","text":"

After you create your merge request, check its control jobs results !

"},{"location":"salesforce-ci-cd-pull-request-azure/","title":"Create a pull request using Azure","text":""},{"location":"salesforce-ci-cd-pull-request-azure/#create-a-pull-request-using-azure","title":"Create a Pull Request using Azure","text":"
  • Go in your online repository in your web browser (example: https://dev.azure.com/mycompany/trailheadapps/dreamhouse-lwc)
  • Go to menu Repos -> Pull Requests
  • Click on New pull request
  • Click on Create
  • Controlling jobs are automatically launched, you can now ask your release manager to validate the merge request
    • If you are a developer, (or even a business consultant depending on the project organization), you may have the responsibility to make sure than controlling jobs are valid (check-deploy job and code-quality job in success) and eventually fix the errors (See Handle merge requests errors)
  • If you need to add additional updates to an existing merge requests, you just this to follow again this guide from the beginning, except the part \"Create a merge request\". Any new commit pushed on a branch where there is already a merge request will trigger again the control jobs.
"},{"location":"salesforce-ci-cd-pull-request-github/","title":"Create a pull request using GitHub","text":""},{"location":"salesforce-ci-cd-pull-request-github/#create-a-pull-request-using-github","title":"Create a Pull Request using GitHub","text":"

Not documented yet, see Create a pull request using Azure, it's almost the same !

You can also create a pull request here to update this documentation :)

"},{"location":"salesforce-ci-cd-release-home/","title":"Salesforce CI/CD Release Manager Guide","text":"

In order to respect the best DevOps practices, it's highly recommended for project teams to have members taking the role of Release Manager

The release manager(s) responsibilities are:

  • Train & support all project members about the use Salesforce CI/CD on the project
  • Provide source-tracked sandboxes to users
  • Validate users merge requests
  • Proceed deployments to major branches/org (UAT,Preprod,Production...)
  • Configure CI/CD project

You can also see specific use cases documentation

  • sfdx-hardis for ISV
  • sfdx-hardis for Conga
"},{"location":"salesforce-ci-cd-retrieve/","title":"Fix sfdx pull issues","text":""},{"location":"salesforce-ci-cd-retrieve/#automated-force-retrieve","title":"Automated force retrieve","text":"

It happens that when calling sf hardis:scratch:pull, some elements are not retrieved.

The most usual cases are updates on:

  • CustomApplication
  • RecordTypes

See how to configure .sfdx-hardis to force the retrieve of metadatas with autoRetrieveWhenPull property.

"},{"location":"salesforce-ci-cd-retrieve/#manual-retrieve","title":"Manual Retrieve","text":"

You can also use command to manually retrieve metadatas, but it will pull a lot of metadatas so you will have to carefully select them for your commit.

Under the hood

See details in hardis:source:retrieve command documentation

"},{"location":"salesforce-ci-cd-setup-activate-org/","title":"Activate Dev Hub and Sandbox Tracking","text":""},{"location":"salesforce-ci-cd-setup-activate-org/#dev-hub-and-sandbox-tracking","title":"Dev Hub and sandbox tracking","text":"

You must declare an org (usually production) as a DevHub and activate sandbox tracking to be able to work with advanced features of Salesforce DX

  • Login to Dev Hub org
  • Go to Setup -> Dev Hub
  • Activate Dev Hub
  • Activate Sandbox tracking
    • If sandbox were already existing, you need to refresh them if you want their source tracking to be activated
    • To use Create from from an existing sandbox, you need to refresh it before the cloning, else the nex sandbox won't have the tracking activated
"},{"location":"salesforce-ci-cd-setup-activate-org/#major-orgs","title":"Major orgs","text":"

When there is a new state of a major branch (after a merge), a deployment to the related major Org will be automatically triggered by the CI server.

You need to have a Salesforce sandbox corresponding to each major branch.

Example:

  • Branch preprod - create a sandbox named Preprod, cloned from Production org
  • Branch uat - create a sandbox named UAT, cloned from PreProd org
  • Branch integration - create a sandbox named Integration, cloned from UAT org

If you are converting an existing project to CI/CD and already have existing orgs, just create an org Integration, and you'll refresh later UAT and PreProd, once your setup will be more advanced.

"},{"location":"salesforce-ci-cd-setup-auth-azure/","title":"Configure Azure CI/CD variables","text":""},{"location":"salesforce-ci-cd-setup-auth-azure/#define-sfdx-hardis-environment-variables","title":"Define sfdx-hardis environment variables","text":"
  • Go to Project -> Pipelines
  • Select your pipeline
  • Click on Edit , then on Variables
  • Input variable name and value
  • Don't forget to click on save !

More info: Azure documentation

"},{"location":"salesforce-ci-cd-setup-auth-bitbucket/","title":"Configure Bitbucket CI/CD variables","text":""},{"location":"salesforce-ci-cd-setup-auth-bitbucket/#define-sfdx-hardis-environment-variables","title":"Define sfdx-hardis environment variables","text":"
  • Go to Project -> Repository Settings > Repository Variables (you must have Bitbucket authorizations to access this menu)

More info: BitBucket documentation

"},{"location":"salesforce-ci-cd-setup-auth-github/","title":"Configure GitHub CI/CD variables","text":""},{"location":"salesforce-ci-cd-setup-auth-github/#define-sfdx-hardis-environment-variables","title":"Define sfdx-hardis environment variables","text":"
  • Go to Repository -> Settings > Secret and variables -> Actions (you must have Github authorizations to access this menu)
  • Create the new secret with the following info:
    • name: YOUR_VARIABLE_NAME
    • value: Your variable value

More info: GitHub documentation

"},{"location":"salesforce-ci-cd-setup-auth-gitlab/","title":"Configure Gitlab CI/CD variables","text":""},{"location":"salesforce-ci-cd-setup-auth-gitlab/#define-sfdx-hardis-environment-variables","title":"Define sfdx-hardis environment variables","text":"
  • Go to Project -> Settings > CI/CD -> Variables (you must have Gitlab authorizations to access this menu)
  • Create the variable with the following info:
    • name: YOUR_VARIABLE_NAME
    • value: Your variable value
    • Select Mask variable if the value is secured, like credentials or tokens
    • Unselect Protected variable

More info: Gitlab documentation

"},{"location":"salesforce-ci-cd-setup-auth-jenkins/","title":"Configure Jenkins CI/CD credentials","text":""},{"location":"salesforce-ci-cd-setup-auth-jenkins/#define-sfdx-hardis-environment-variables","title":"Define sfdx-hardis environment variables","text":"
  • Go to Dashboard -> Manage Jenkins
  • Under Security tab click on Credentials -> global credentials
  • Click on Add credential , then choose Secret text
  • Input variable name and value
  • Don't forget to click on create !

More info: Jenkins documentation

"},{"location":"salesforce-ci-cd-setup-auth/","title":"Configure CI Server authentication to Salesforce orgs","text":""},{"location":"salesforce-ci-cd-setup-auth/#major-orgs","title":"Major orgs","text":"

To automate deployments from major branches to their related org, you need to configure the secure authentication from CI server to a SF connected app.

Note: You need openssl installed on your computer (available in Git bash)

  • Remain in your initialization branch cicd, or a sub branch of your lowest level major branch (usually integration)
  • For each major branch to link to an org, run the sfdx-hardis command Configuration -> (sf hardis:project:configure:auth)

For example, run the command for integration, uat, preprod and production major branches.

If messages ask you to run twice the same command, it's normal, it's for technical reasons :)

If you have errors in your apex tests classes, you may not be able to configure the app for Production org. You will need do create the connected app manually by following the instructions in yellow in the error message. You can do it later, after having succeeded to merge the first merge request in lower major branch (usually integration)

Under the hood

This command will create/update:

  • .sfdx-hardis.yml configuration file (repo)
  • Self signed certificate (encrypted in repo as .key)
  • Connected App (uploaded to org via metadata api)
  • CI environment variables (manually set in CI/CD server UIs)

At runtime, we use OAuth 2.0 JSON Web Tokens (JWT) bearer flow with the client Id stored in secured CI/CD Variable + the Certificate decrypted on the fly using token stored in secured CI/CD variable.

See how to set CI variables on different Git providers:

  • Gitlab tutorial
  • Azure tutorial
  • GitHub tutorial
  • BitBucket tutorial
  • Jenkins tutorial
"},{"location":"salesforce-ci-cd-setup-auth/#dev-hub","title":"Dev Hub","text":"

If you are using scratch orgs, you need to also configure authentication for the Dev Hub (even if you already configured authentication for production org)

To do that, run the following command

sf hardis:project:configure:auth --devhub\n
"},{"location":"salesforce-ci-cd-setup-existing-org/","title":"Initialize sfdx sources from Salesforce org","text":"

If this is a new Salesforce project, or if you want to setup CI/CD in incremental mode, you can skip this step and directly go to Create first merge request.

Thanks to tracked sandboxes, you can also decide to opt for an half-incremental init, with only some metadata types like Apex, LWC & Permission sets. In that case retrieve manually the metadatas you need, for example with Org Browser.

If you want to go for a full init setup, follow the steps below !

  • Retrieve Metadatas
  • Automated Metadatas Cleaning
    • Remove Managed items
    • Remove (hidden) files
    • Remove empty items
    • Standard objects without custom
  • Manual Metadata Cleaning
  • Retrieve installed packages
  • Create first merge request
"},{"location":"salesforce-ci-cd-setup-existing-org/#retrieve-metadatas","title":"Retrieve Metadatas","text":"
  • Run the following command that will retrieve locally all the metadatas of production org

sf hardis:org:retrieve:sources:dx --shape -u YOURSOURCEORGUSERNAME

  • In case you get an error:
    • Run the generate package xml command : hardis:org:generate:packagexmlfull
    • Clean up the generated package created by removing the unnecessary metadatas
    • Run retrieve metadata command : sf project:retrieve:start

Example :

  • sf hardis:org:generate:packagexmlfull --targetusername nico@example.com --outputfile ./packagexmlfull.xml
  • Remove Document part on packagexmlfull.xml
        <types>\n        <members>Doc1</members>\n        <members>Doc2</members>\n        <members>Doc3</members>\n        <name>Document</name>\n    </types>\n
  • sf project:retrieve:start -x ./packagexmlfull.xml --ignore-conflicts
"},{"location":"salesforce-ci-cd-setup-existing-org/#automated-metadatas-cleaning","title":"Automated Metadatas Cleaning","text":"

You have way too many metadatas locally, including standard and managed items that are not customize so are not needed in the repository.

Proceed to the following steps to automatically remove many of them, then proceed to the final manual cleaning

"},{"location":"salesforce-ci-cd-setup-existing-org/#remove-managed-items","title":"Remove Managed items","text":"

Run the following command to delete all elements with a namespace.

sf hardis:project:clean:manageditems --namespace SOMENAMESPACE\n
"},{"location":"salesforce-ci-cd-setup-existing-org/#remove-hidden-files","title":"Remove (hidden) files","text":"

Some items have no namespace but are managed anyway, and contain (hidden), so they must me deleted with the following command.

sf hardis:project:clean:hiddenitems\n
"},{"location":"salesforce-ci-cd-setup-existing-org/#remove-empty-items","title":"Remove empty items","text":"

Some files are empty and do not need to be kept in repository, remove them using the following command.

sf hardis:project:clean:emptyitems\n
"},{"location":"salesforce-ci-cd-setup-existing-org/#standard-objects-without-custom","title":"Standard objects without custom","text":"

The retrieve command pulled all standard objects and fields.

Those which has never been customized do not need to remain in repository, delete them using the following command (that can take some time)

sf hardis:project:clean:standarditems\n
"},{"location":"salesforce-ci-cd-setup-existing-org/#manual-metadata-cleaning","title":"Manual Metadata Cleaning","text":"

Automated Metadata cleaning removed a lot of items, but many are remaining that are useless in the repo.

Manually delete files (or even folders) that are maintained directly in production org

  • applications: Delete the ones starting with standard__
  • \u00e0ppMenus: Delete all folder
  • cleanDataServices: Delete all folder
  • dashboards: Delete all user dashboards
  • emailServices: Delete all folder
  • flowDefinitions : Delete all folder (Salesforce now uses flow folder)
  • installedPackages: Delete all folder
  • layouts: Delete all standard layouts that has not been customized
  • profiles : Delete all standard profiles
  • profilePasswordPolicies: Delete all folder
  • profileSessionSettings: Delete all folder,
  • reports: Delete all reports that have been created directly in production org
"},{"location":"salesforce-ci-cd-setup-existing-org/#retrieve-installed-packages","title":"Retrieve installed packages","text":"

Run the following command to retrieve packages installed on production org

sf hardis:org:retrieve:packageconfig -u YOUR_PROD_ORG_USER

This will update file config/.sfdx-hardis.yml

  • Keep only the packages that you are using in all orgs.
  • Define installDuringDeployments property to true if you need this package installed on all orgs
  • Define installOnScratchOrgs property to true if you are using scratch orgs and need this package installed when you create a new scratch org

Example:

installedPackages:\n  - Id: 0A37Z000000AtDYSA0\n    SubscriberPackageId: 033i0000000LVMYAA4\n    SubscriberPackageName: Marketing Cloud\n    SubscriberPackageNamespace: et4ae5\n    SubscriberPackageVersionId: 04t6S000001UjutQAC\n    SubscriberPackageVersionName: Marketing Cloud\n    SubscriberPackageVersionNumber: 238.3.0.2\n    installOnScratchOrgs: true\n    installDuringDeployments: true\n  - Id: 0A35r0000009F9CCAU\n    SubscriberPackageId: 033b0000000Pf2AAAS\n    SubscriberPackageName: Declarative Lookup Rollup Summaries Tool\n    SubscriberPackageNamespace: dlrs\n    SubscriberPackageVersionId: 04t5p000001BmLvAAK\n    SubscriberPackageVersionName: Release\n    SubscriberPackageVersionNumber: 2.15.0.9\n    installOnScratchOrgs: true\n    installDuringDeployments: true\n
"},{"location":"salesforce-ci-cd-setup-existing-org/#create-first-merge-request","title":"Create first merge request","text":"

Don't forget to run and to follow other instructions before creating your initial merge request !

Time to create the first merge request !

You'll probably have many updates to perform in new commits before having all jobs in green :)

"},{"location":"salesforce-ci-cd-setup-git/","title":"Configure Git Branches for Salesforce CI/CD","text":"
  • Create git repository
  • Create major branches
    • Small project
    • Medium project
    • Complex project
  • Protect major branches
  • Define merge rules
"},{"location":"salesforce-ci-cd-setup-git/#create-git-repository","title":"Create git repository","text":"

Your git repository will be used to store and manage the versioning of your Salesforce DX sources

  • Create a new repository, for example myclient-sfdx
    • Select Initialize repository with a README
"},{"location":"salesforce-ci-cd-setup-git/#create-major-branches","title":"Create major branches","text":"

In Repository -> Branches, create the branch tree according to the complexity of your project

Below are examples of branches tree that you can define.

"},{"location":"salesforce-ci-cd-setup-git/#small-project","title":"Small project","text":"
  • main (will be related to Production org)
    • preprod (will be related to PreProd org)
"},{"location":"salesforce-ci-cd-setup-git/#medium-project","title":"Medium project","text":"
  • main (will be related to Production org)
    • preprod (will be related to PreProd org)
      • integration (will be related to Integration org)
"},{"location":"salesforce-ci-cd-setup-git/#complex-project","title":"Complex project","text":"
  • main (will be related to Production org)
    • preprod (will be related to PreProd org)
      • uat (will be related to UAT org)
        • integration (will be related to Integration org)

Example of branching strategy

"},{"location":"salesforce-ci-cd-setup-git/#protect-major-branches","title":"Protect major branches","text":"

To avoid messes, protected branches must be updated only using Merge Requests

  • Go to menu Settings -> Repository
  • Define your developments target branch (usually integration) as Default Branch
  • Protect all branches that will have a corresponding Salesforce org (main, preprod, uat, integration...)

Recommended practice is to set Maintainer in Allowed to merge to all protected branches, except integration

Example

"},{"location":"salesforce-ci-cd-setup-git/#define-merge-rules","title":"Define merge rules","text":"

Let's make sure that merge request jobs will be valid before being merged ! (can be deactivated later but at your own risk)

  • Go in menu Settings -> General , then in section Merge requests (expand)
  • Leave all default values, except checkbox Pipelines must succeed that must be checked

"},{"location":"salesforce-ci-cd-setup-home/","title":"Setup a Salesforce CI/CD Project","text":"
  • Pre-requisites
  • Setup steps
"},{"location":"salesforce-ci-cd-setup-home/#pre-requisites","title":"Pre-requisites","text":"
  • Training with Git and Salesforce DX
    • If you don't have experience with them, here are links to learning resources
      • Git Tuto
      • SFDX Trailmix
  • Install necessary applications on your computer
  • Access to a Git server (Gitlab, GitHub, Azure...) with CI/CD server minutes
  • Access to a Salesforce production org
"},{"location":"salesforce-ci-cd-setup-home/#setup-steps","title":"Setup steps","text":"
  • Create git repository and configure branches
  • Activate DevHub or Sandbox Tracking
  • Initialize sfdx project
  • Configure authentication
  • Retrieve sources from an existing org (optional)
  • Configure integrations
  • Configure Salesforce DX project (follow all steps !)
  • Make the first merge request !
"},{"location":"salesforce-ci-cd-setup-init-project/","title":"Initialize SFDX Project","text":"
  • Clone locally the repository that you created in previous step (or reuse an existing sfdx project repo)
  • Create a new git branch named cicd under your lower major branch (usually integration)
  • Run command Configuration -> (sf hardis:project:create) and select options to create a new sfdx-hardis project.
  • Open file manifest/package.xml and replace the content by the following code
<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Package xmlns=\"http://soap.sforce.com/2006/04/metadata\">\n    <version>59.0</version> <!-- use current latest Salesforce api version -->\n</Package>\n
  • IF you are using Gitlab CI and sandboxes only (not scratch orgs), open gitlab-ci-config.yml at the root of the repository, and set variable USE_SCRATCH_ORGS to \"false\"
  • Depending your git provider, keep the related workflow files and delete the others
    • Gitlab
      • gitlab-ci.yml
      • gitlab-ci-config.yml
    • Azure
      • azure-pipelines-checks.yml
      • azure-pipelines-deployment.yml
    • GitHub:
      • Folder .github/workflows
    • Bitbucket
      • bitbucket-pipelines.yml

Some workflow files contain additional configuration instructions, please read the comments at the beginning of the files !

You can now go to step Setup CI Authentication

"},{"location":"salesforce-ci-cd-setup-integration-api/","title":"Configure API notifications from Salesforce CI/CD","text":""},{"location":"salesforce-ci-cd-setup-integration-api/#api-integration","title":"API Integration","text":"

You can send notifications to an external API endpoints, for example to build Grafana dashboards

  • Deployment from a major branch to a major Salesforce org (ex: integration git branch to Integration Org)
  • Salesforce Org Monitoring
    • Latest updates
    • Failing apex tests
    • Monitoring checks notifications
"},{"location":"salesforce-ci-cd-setup-integration-api/#logs-configuration","title":"Logs Configuration","text":"

Define the following CI/CD variables:

  • NOTIF_API_URL : API endpoint
  • NOTIF_API_BASIC_AUTH_USERNAME : Basic auth username (if using Basic Auth)
  • NOTIF_API_BASIC_AUTH_PASSWORD : Basic auth password/token (if using Basic Auth)
  • NOTIF_API_BEARER_TOKEN : Bearer token (if using bearer auth)

Examples of configuration:

NOTIF_API_URL=https://logs-prod-012.grafana.net/loki/api/v1/push\nNOTIF_API_BASIC_AUTH_USERNAME=3435645645\nNOTIF_API_BASIC_AUTH_PASSWORD=GHTRGDHDHdhghg23345DFG^sfg!ss\n
NOTIF_API_URL=https://my.custom.endpoint.net\nNOTIF_API_BEARER_TOKEN=DDHGHfgfgjfhQESRDTHFKGKHFswgFHDHGDH\n

Example of logs sent to Loki:

{\n  \"streams\": [\n    {\n      \"stream\": {\n        \"source\": \"sfdx-hardis\",\n        \"type\": \"LINT_ACCESS\",\n        \"orgIdentifier\": \"hardis-group\",\n        \"gitIdentifier\": \"monitoring-hardis-org/monitoring_hardis_group\",\n        \"severity\": \"warning\"\n      },\n      \"values\": [\n        [\n          \"1715530820301000000\",\n          \"{\\\"metric\\\":3,\\\"_dateTime\\\":\\\"2024-05-12T16:20:20.301Z\\\",\\\"_severityIcon\\\":\\\"\u26a0\ufe0f\\\",\\\"_title\\\":\\\"\u26a0\ufe0f 3 custom elements have no access defined in any Profile or Permission set in monitoringhardisgroup\\\",\\\"_logBodyText\\\":\\\"\u26a0\ufe0f 3 custom elements have no access defined in any Profile or Permission set in monitoringhardisgroup\\\\n\\\\nfield\\\\n\\\\n\u2022 Activity.DBActivityType__c\\\\n\\\\n\u2022 Activity.IdExterneCARRENET__c\\\\n\\\\n\u2022 Activity.Typederendezvous_c\\\\n\\\\nLinks:\\\\n\\\\n  View Job: https://gitlab.onpremise.com/busalesforce/hardis-group-interne/monitoring-hardis-org/-/jobs/12345\\\\n\\\\nPowered by sfdx-hardis: https://sfdx-hardis.cloudity.com\\\",\\\"_logElements\\\":[{\\\"type\\\":\\\"field\\\",\\\"element\\\":\\\"Activity.DB_Activity_Type__c\\\",\\\"severity\\\":\\\"warning\\\",\\\"severityIcon\\\":\\\"\u26a0\ufe0f\\\"},{\\\"type\\\":\\\"field\\\",\\\"element\\\":\\\"Activity.IdExterneCARRENET__c\\\",\\\"severity\\\":\\\"warning\\\",\\\"severityIcon\\\":\\\"\u26a0\ufe0f\\\"},{\\\"type\\\":\\\"field\\\",\\\"element\\\":\\\"Activity.Type_de_rendez_vous__c\\\",\\\"severity\\\":\\\"warning\\\",\\\"severityIcon\\\":\\\"\u26a0\ufe0f\\\"}],\\\"_metrics\\\":{\\\"ElementsWithNoProfileOrPermissionSetAccess\\\":3},\\\"_metricsKeys\\\":[\\\"ElementsWithNoProfileOrPermissionSetAccess\\\"],\\\"_jobUrl\\\":\\\"https://gitlab.onpremise.com/busalesforce/hardis-group-interne/monitoring-hardis-org/-/jobs/399629\\\"}\"\n        ]\n      ]\n    }\n  ]\n}\n
"},{"location":"salesforce-ci-cd-setup-integration-api/#metrics-configuration","title":"Metrics Configuration","text":"

Additionally, you can send metrics in Prometheus format to a secondary API endpoint.

The configuration is the same than for logs, but with different variable names.

  • NOTIF_API_METRICS_URL
  • NOTIF_API_METRICS_BASIC_AUTH_USERNAME
  • NOTIF_API_METRICS_BASIC_AUTH_PASSWORD
  • NOTIF_API_METRICS_BEARER_TOKEN

Example of configuration:

NOTIF_API_METRICS_URL=https://influx-prod-72-prod-eu-west-2.grafana.net/api/v1/push/influx/write\nNOTIF_API_METRICS_BASIC_AUTH_USERNAME=345673\nNOTIF_API_METRICS_BASIC_AUTH_PASSWORD=GHTRGDHDHdhghg23345DFG^sfg!ss\n

Example of metrics sent to Prometheus

ApexTestsFailingClasses,source=sfdx-hardis,type=APEX_TESTS,orgIdentifier=hardis-group,gitIdentifier=monitoring-hardis-org/monitoring_hardis_group metric=0.00\nApexTestsCodeCoverage,source=sfdx-hardis,type=APEX_TESTS,orgIdentifier=hardis-group,gitIdentifier=monitoring-hardis-org/monitoring_hardis_group metric=90.00\n
"},{"location":"salesforce-ci-cd-setup-integration-api/#troubleshooting","title":"Troubleshooting","text":"

If you want to see the content of the API notifications in execution logs, you can define NOTIF_API_DEBUG=true

"},{"location":"salesforce-ci-cd-setup-integration-api/#grafana-setup","title":"Grafana Setup","text":"

If you don't have a Grafana server, you can use Grafana Cloud Free Tier (14 days of logs & metrics retention + 3 users, no credit card required, free forever)

"},{"location":"salesforce-ci-cd-setup-integration-api/#create-grafana-account","title":"Create Grafana Account","text":"

Create a Grafana Cloud Free account at this url

Input a Grafana Cloud org name (sfdxhardis in the example)

Next screen, you can skip setup

"},{"location":"salesforce-ci-cd-setup-integration-api/#gather-urls-auth-info","title":"Gather URLs & auth info","text":"

Create a notepad when you copy paste the following text

NOTIF_API_URL=\nNOTIF_API_BASIC_AUTH_USERNAME=\nNOTIF_API_BASIC_AUTH_PASSWORD=\nNOTIF_API_METRICS_URL=\nNOTIF_API_METRICS_BASIC_AUTH_USERNAME=\nNOTIF_API_METRICS_BASIC_AUTH_PASSWORD=\n
"},{"location":"salesforce-ci-cd-setup-integration-api/#get-loki-configuration","title":"Get Loki configuration","text":"

Go to Connections -> Data Sources and click on grafanacloud-YOURORGNAME-logs (Loki)

Build Logs push url

  • Copy value of Connection URL (something like https://logs-prod-012.grafana.net/)
  • Add /loki/api/v1/push at the end
  • Copy value to variables NOTIF_API_URL

Example: NOTIF_API_URL=https://logs-prod-012.grafana.net/loki/api/v1/push

Copy value of Authentication -> User and paste it with variable NOTIF_API_BASIC_AUTH_USERNAME

Example: NOTIF_API_BASIC_AUTH_USERNAME=898189

Leave NOTIF_API_BASIC_AUTH_PASSWORD empty for now, you can't get it here

See Grafana documentation for more info

"},{"location":"salesforce-ci-cd-setup-integration-api/#get-prometheus-configuration","title":"Get Prometheus configuration","text":"

Go to Connections -> Data Sources and click on grafanacloud-YOURORGNAME-prom (Prometheus)

Build Metrics push url

  • Copy value of Connection URL (something like https://prometheus-prod-24-prod-eu-west-2.grafana.net/api/prom)
  • Replace prometheus by influx
  • Replace api/prom by api/v1/push/influx/write
  • Then copy value to variables NOTIF_API_METRICS_URL

Example: NOTIF_API_METRICS_URL=https://influx-prod-24-prod-eu-west-2.grafana.net/api/v1/push/influx/write

Copy value of Authentication -> User and paste it with variable NOTIF_API_METRICS_BASIC_AUTH_USERNAME

Example: NOTIF_API_METRICS_BASIC_AUTH_USERNAME=1596503

Leave NOTIF_API_METRICS_BASIC_AUTH_PASSWORD empty for now, you can't get it here

See Grafana documentation for more info

"},{"location":"salesforce-ci-cd-setup-integration-api/#create-service-account","title":"Create Service Account","text":"

Go to Administration -> Users and Access -> Cloud Access Policies, then click on Create Access Policy

Create the access policy

  • Define sfdxhardis as name and display name
  • Select write for items metrics, logs, traces, profiles, alerts (only metrics and logs are used today, but who knows hat new features we'll release in the future !)
  • Click on Create

On the new Access Policy sfdxhardis, click on Add Token at the bottom right

Name it sfdxhardis-token, let No expiration then click Create

On the next screen, click on Copy to clipboard then paste in your notepad in front of variables NOTIF_API_BASIC_AUTH_PASSWORD and NOTIF_API_METRICS_BASIC_AUTH_PASSWORD

Example:

NOTIF_API_BASIC_AUTH_PASSWORD=glc_eyJvIjoiMTEzMjI4OCIsIm4iOiJzZmR4aGFyZGlzLXNmZHhoYXJkaXMtdG9rZW4iLCJrIjoiN0x6MzNXS0hKR1J5ODNsMVE5NU1IM041IiwibSI6eyJyXN0LTIifX0=\nNOTIF_API_METRICS_BASIC_AUTH_PASSWORD=glc_eyJvIjoiMTEzMjI4OCIsIm4iOiJzZmR4aGFyZGlzLXNmZHhoYXJkaXMtdG9rZW4iLCJrIjoiN0x6MzNXS0hKR1J5ODNsMVE5NU1IM041IiwibSI6eyJyXN0LTIifX0=\n
"},{"location":"salesforce-ci-cd-setup-integration-api/#configure-ci-variables-on-repository","title":"Configure CI variables on repository","text":"

Now configure the 6 variables on the monitoring repository. (Ignore other paragraphs, except those who explain how to modify the pipeline YML to access protected variables)

  • GitHub
  • Gitlab
  • Azure
  • BitBucket

Now you can force a run of your monitoring job (just add a dumb commit on a monitoring_xxxx branch to trigger it)

Optionally , you can look in the logs, you should see [ApiProvider] and [ApiMetricProvider] items.

"},{"location":"salesforce-ci-cd-setup-integration-api/#download-sfdx-hardis-dashboards","title":"Download sfdx-hardis dashboards","text":"

Download all sfdx-hardis Dashboard JSON files from this sfdx-hardis repo folder

"},{"location":"salesforce-ci-cd-setup-integration-api/#create-dashboard-folder","title":"Create Dashboard folder","text":"

Go in menu Dashboards then click on New then New folder

Create folder Sfdx-hardis Dashboards

"},{"location":"salesforce-ci-cd-setup-integration-api/#import-default-sfdx-hardis-grafana-dashboards","title":"Import default sfdx-hardis Grafana Dashboards","text":"

For each downloaded Dashboard JSON file, process the following actions.

Click New then Import

Click on Upload Dashboard JSON File and select one of the Dashboards JSON files you downloaded on your computer.

  • Let Name, Folder and UID default values
  • Select your Loki or Prometheus source. They can be:
    • grafanacloud-YOURORGNAME-logs (Loki)
    • grafanacloud-YOURORGNAME-prom (Prometheus)

Click Import

__

Repeat the operation for all Dashboard JSON files, and you're all set !

"},{"location":"salesforce-ci-cd-setup-integration-azure-boards/","title":"Configure Integrations between sfdx-hardis and Azure Boards Work Items","text":"
  • Azure Boards integration
    • Update Work Items
  • Technical notes
"},{"location":"salesforce-ci-cd-setup-integration-azure-boards/#azure-boards-integration","title":"Azure Boards integration","text":"

If you use Azure Work Items on your project, sfdx-hardis can use it to enrich its integrations

Sfdx-hardis will automatically analyze commits and PR/MR descriptions to collect Work Items references !

Make sure to link your Work Items to your Pull Requests before submitting them !

"},{"location":"salesforce-ci-cd-setup-integration-azure-boards/#update-work-items","title":"Update Work Items","text":"

Add comments and tags on JIRA tickets when they are deployed in a major org

Default tag is UPPERCASE(branch_name) + \"_DEPLOYED\".

To override it, define env variable DEPLOYED_TAG_TEMPLATE, that must contain {BRANCH}.

Example: DEPLOYED_TO_{BRANCH}

"},{"location":"salesforce-ci-cd-setup-integration-azure-boards/#technical-notes","title":"Technical notes","text":"

This integration use the following variables, that must be available from the pipelines:

  • SYSTEM_COLLECTIONURI
  • SYSTEM_ACCESSTOKEN
  • SYSTEM_TEAMPROJECT
  • BUILD_REPOSITORY_ID
"},{"location":"salesforce-ci-cd-setup-integration-azure/","title":"Configure Integrations between sfdx-hardis and Azure Pipelines","text":""},{"location":"salesforce-ci-cd-setup-integration-azure/#azure-pull-request-notes","title":"Azure Pull Request notes","text":"

In order to avoid to have to open job logs to see deployment errors, sfdx-hardis can post them as a thread on the Pull Request UI

To use this capability:

  • A build policy must be defined

    • See https://docs.microsoft.com/en-US/azure/devops/repos/git/branch-policies?view=azure-devops&tabs=browser#build-validation
  • You must allow Contribute and Contribute to Pull Requests on your Build Service (Settings -> Repositories -> Select your build service)

Everytime you will make a pull request, the CI job will post its result as comment !

  • Example with deployment errors

  • Example with failing test classes

  • Example when all is ok :)

Notes:

  • This integration works with sfdx-hardis pipeline, but also on home-made pipelines, just call sf hardis:project:deploy:start instead of sf project:deploy:start !
  • This integration use the following variables:
    • SYSTEM_ACCESSTOKEN: $(System.AccessToken)
    • CI_SFDX_HARDIS_AZURE_TOKEN: $(System.AccessToken)
    • SYSTEM_COLLECTIONURI: $(System.CollectionUri)
    • SYSTEM_JOB_DISPLAY_NAME: $(System.JobDisplayName)
    • SYSTEM_JOB_ID: $(System.JobId)
    • SYSTEM_PULLREQUEST_PULLREQUESTID: $(System.PullRequest.PullRequestId)
    • SYSTEM_TEAMPROJECT: $(System.TeamProject)
    • BUILD_BUILD_ID: $(Build.BuildId)
    • BUILD_REPOSITORY_ID: $(Build.Repository.ID)
"},{"location":"salesforce-ci-cd-setup-integration-bitbucket/","title":"Configure Integrations between sfdx-hardis and Bitbucket Pipelines","text":""},{"location":"salesforce-ci-cd-setup-integration-bitbucket/#bitbucket-pull-request-comments","title":"Bitbucket Pull Request comments","text":"

In order to avoid to have to open job logs to see deployment errors, sfdx-hardis can post them as a comment on the Pull Request UI

To use this capability:

  • Go to Repository Settings -> Access Tokens Create Repository Access Token with the following scopes:
    • pullrequest
    • pullrequest:write
    • repository
    • repository:write
  • Go to Repository Settings > Repository Variables Create a variable named CI_SFDX_HARDIS_BITBUCKET_TOKEN and provide the access token value

Everytime you will make a pull request, the CI job will post its result as a comment !

  • Example when all is ok :)

Notes:

  • This integration works with sfdx-hardis pipeline, but also on home-made pipelines, just call sf hardis:project:deploy:start instead of sf project:deploy:start !
  • This integration uses the following variables:
    • CI_SFDX_HARDIS_BITBUCKET_TOKEN
    • BITBUCKET_WORKSPACE
    • BITBUCKET_REPO_SLUG
    • BITBUCKET_BRANCH
    • BITBUCKET_PR_ID
    • BITBUCKET_BUILD_NUMBER
"},{"location":"salesforce-ci-cd-setup-integration-email/","title":"Configure Email notifications from Salesforce CI/CD","text":""},{"location":"salesforce-ci-cd-setup-integration-email/#email-integration","title":"Email Integration","text":"

You can receive notifications on one or multiple e-mail addresses when sfdx-hardis events are happening:

  • Deployment from a major branch to a major Salesforce org (ex: integration git branch to Integration Org)
  • Salesforce Org Monitoring
    • Latest updates
    • Failing apex tests
    • Monitoring checks notifications

Note: Salesforce email sending capabilities are used, so every email will count in your org daily email limit.

"},{"location":"salesforce-ci-cd-setup-integration-email/#configuration","title":"Configuration","text":"

Define CI/CD variable NOTIF_EMAIL_ADDRESS with the related email(s)

Examples:

  • NOTIF_EMAIL_ADDRESS=admin@cloudity.com
  • NOTIF_EMAIL_ADDRESS=admin@cloudity.com,another.user@cloudity.com,nico@cloudity.com
"},{"location":"salesforce-ci-cd-setup-integration-email/#troubleshooting","title":"Troubleshooting","text":"

If the emails are not sent, apply the following configuration on the Monitoring / Deployment user settings

  • Send through Salesforce

That's all, you're all set !

"},{"location":"salesforce-ci-cd-setup-integration-generic-ticketing/","title":"Configure Integrations between sfdx-hardis and any ticketing system","text":"
  • Generic ticketing integration
  • Configuration
    • GENERIC_TICKETING_PROVIDER_REGEX
    • GENERIC_TICKETING_PROVIDER_URL_BUILDER
  • Gitlab configuration
  • Technical notes
"},{"location":"salesforce-ci-cd-setup-integration-generic-ticketing/#generic-ticketing-integration","title":"Generic ticketing integration","text":"

If you use a ticketing system on your project, sfdx-hardis can use it to enrich its integrations

Sfdx-hardis will automatically analyze commits and PR/MR descriptions to collect tickets and build their urls !

"},{"location":"salesforce-ci-cd-setup-integration-generic-ticketing/#configuration","title":"Configuration","text":"

You need to define 2 environment variables in your CI/CD configuration

"},{"location":"salesforce-ci-cd-setup-integration-generic-ticketing/#generic_ticketing_provider_regex","title":"GENERIC_TICKETING_PROVIDER_REGEX","text":"

Regular expression allowing to detect your ticketing system identifiers in the commits / PR texts.

You can use https://regex101.com/ to check your Regular Expression.

Example: ([R|I][0-9]+-[0-9]+) to detect EasyVista references, that can look like I240103-0133 or R230904-0026

"},{"location":"salesforce-ci-cd-setup-integration-generic-ticketing/#generic_ticketing_provider_url_builder","title":"GENERIC_TICKETING_PROVIDER_URL_BUILDER","text":"

Template string allowing to build a hyperlink from a ticket identifier.

Must contain a {REF} segment that will be replaced by the ticket identifier.

Example: https://instance.easyvista.com/index.php?ticket={REF}

"},{"location":"salesforce-ci-cd-setup-integration-generic-ticketing/#gitlab-configuration","title":"Gitlab configuration","text":"

If you are using Gitlab, you need to update the Merge Request Settings

Go to Project -> Settings -> Merge Requests

Update Merge Commit Message Template with the following value

%{title} Merge branch '%{source_branch}' into '%{target_branch}'\n\n%{issues}\n\nSee merge request %{reference}\n\n%{description}\n\n%{all_commits}\n

Update Squash Commit Message Template with the following value

%{title} Merge branch '%{source_branch}' into '%{target_branch}'\n\n%{issues}\n\nSee merge request %{reference}\n\n%{description}\n\n%{all_commits}\n
"},{"location":"salesforce-ci-cd-setup-integration-generic-ticketing/#technical-notes","title":"Technical notes","text":"

This integration use the following variables, that must be available from the pipelines:

  • GENERIC_TICKETING_PROVIDER_REGEX
  • GENERIC_TICKETING_PROVIDER_URL_BUILDER
"},{"location":"salesforce-ci-cd-setup-integration-github/","title":"Configure Integrations between sfdx-hardis and GitHub","text":""},{"location":"salesforce-ci-cd-setup-integration-github/#github-pull-requests-comments","title":"GitHub Pull Requests comments","text":"

In order to avoid to have to open job logs to see deployment errors, sfdx-hardis can post them as Comment on the Pull Request UI

To use this capability, all you need is to have permissions on your workflows and send your GITHUB_TOKEN (see full example)

    permissions:\n      pull-requests: write\n\n...\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        FORCE_COLOR: \"1\"\n

Everytime you will make a Pull Request, the CI job will post its result as comment !

  • Example with deployment success

  • Example with deployment errors

Notes:

  • This integration works with sfdx-hardis pipeline, but also on home-made pipelines, just call sf hardis:project:deploy:start instead of sf project:deploy:start !
  • This integration use the following variables:

    • GITHUB_TOKEN (provided by GitHub but has to be send as option to the deployment jobs)
"},{"location":"salesforce-ci-cd-setup-integration-gitlab/","title":"Configure Integrations between sfdx-hardis and Gitlab","text":""},{"location":"salesforce-ci-cd-setup-integration-gitlab/#gitlab-merge-request-notes","title":"Gitlab Merge request notes","text":"

In order to avoid to have to open job logs to see deployment errors, sfdx-hardis can post them as Notes on the Merge Request UI

To use this capability:

  • Go to Settings -> Access Tokens -> Create a project access token with level Developer and scope api, and name it SFDX HARDIS BOT

  • Go to Settings -> CI/CD -> Variables -> Create a variable named CI_SFDX_HARDIS_GITLAB_TOKEN and past the access token value

Everytime you will make a merge request, the CI job will post its result as comment !

  • Example with deployment errors

  • Example with failing test classes

Notes:

  • This integration works with sfdx-hardis pipeline, but also on home-made pipelines, just call sf hardis:project:deploy:start instead of sf project:deploy:start !
  • This integration use the following variables:
    • CI_SFDX_HARDIS_GITLAB_TOKEN
    • CI_SERVER_URL (provided by Gitlab CI)
    • CI_PROJECT_ID (provided by Gitlab CI)
    • CI_MERGE_REQUEST_IID (provided by Gitlab CI)
    • CI_JOB_NAME (provided by Gitlab CI)
    • CI_JOB_URL (provided by Gitlab CI)
    • GITLAB_API_REJECT_UNAUTHORIZED: set to \"false\" if you want to allow connection even without certificate (can be useful on on-premise GitLab instance)
"},{"location":"salesforce-ci-cd-setup-integration-jira/","title":"Configure Integrations between sfdx-hardis and Jira","text":"
  • Jira integration
    • For git providers
    • For notifications providers
    • Update JIRA issues
  • Global Configuration
    • Identify JIRA tickets
    • Jira Cloud
    • Jira On-Premise
  • Gitlab configuration
  • Technical notes
"},{"location":"salesforce-ci-cd-setup-integration-jira/#jira-integration","title":"Jira integration","text":"

If you use JIRA on your project, sfdx-hardis can use it to enrich its integrations

Sfdx-hardis will automatically analyze commits and PR/MR descriptions to collect JIRA tickets URLS !

You can use the full URL of JIRA tickets in your commits and PR/MR descriptions.

Use https://sfdx-hardis.atlassian.net/browse/CLOUDITY-4 , not CLOUDITY-4 !

If you don't use full URL, a default expression will be used, that you can override for a better accuracy (see Identify JIRA Tickets )

In that case, CLOUDITY-4 will be detected, but make sure that JIRA_HOST is defined

"},{"location":"salesforce-ci-cd-setup-integration-jira/#for-git-providers","title":"For git providers","text":"

Github, Gitlab, Azure, Bitbucket: Post references to JIRA tickets in PR/MR comments

"},{"location":"salesforce-ci-cd-setup-integration-jira/#for-notifications-providers","title":"For notifications providers","text":"

Slack, MsTeams: Add deployed JIRA tickets in deployment notifications

"},{"location":"salesforce-ci-cd-setup-integration-jira/#update-jira-issues","title":"Update JIRA issues","text":"

Add comments and tags on JIRA tickets when they are deployed in a major org

Default tag is UPPERCASE(branch_name) + \"_DEPLOYED\".

To override it, define env variable DEPLOYED_TAG_TEMPLATE, that must contain {BRANCH}.

Example: DEPLOYED_TO_{BRANCH}

"},{"location":"salesforce-ci-cd-setup-integration-jira/#global-configuration","title":"Global configuration","text":""},{"location":"salesforce-ci-cd-setup-integration-jira/#identify-jira-tickets","title":"Identify JIRA Tickets","text":"

Define CI/CD variable JIRA_TICKET_REGEX with a regular expression allowing to identify the JIRA tickets of your project in commit& Pull Requests titles & bodies, for example (CLOUDITY-[0-9]+)

"},{"location":"salesforce-ci-cd-setup-integration-jira/#jira-cloud","title":"Jira Cloud","text":"

Define CI/CD variables

  • JIRA_HOST (example: https://sfdx-hardis.atlassian.net/)
  • JIRA_EMAIL (example: nicolas.vuillamy@cloudity.com)
  • JIRA_TOKEN , to create following Atlassian documentation
"},{"location":"salesforce-ci-cd-setup-integration-jira/#jira-on-premise","title":"Jira On-Premise","text":"

Note: Does not seems to work with every on-premise JIRA servers

Define CI/CD variables

  • JIRA_HOST (examples: https://jira.cloudity.com/ , or with path like https://pid.cloudity.com/jira/)
  • JIRA_PAT, to create following Atlassian Documentation (section Creating PATs in the application)
"},{"location":"salesforce-ci-cd-setup-integration-jira/#gitlab-configuration","title":"Gitlab configuration","text":"

If you are using Gitlab, you need to update the Merge Request Settings

Go to Project -> Settings -> Merge Requests

Update Merge Commit Message Template with the following value

%{title} Merge branch '%{source_branch}' into '%{target_branch}'\n\n%{issues}\n\nSee merge request %{reference}\n\n%{description}\n\n%{all_commits}\n

Update Squash Commit Message Template with the following value

%{title} Merge branch '%{source_branch}' into '%{target_branch}'\n\n%{issues}\n\nSee merge request %{reference}\n\n%{description}\n\n%{all_commits}\n
"},{"location":"salesforce-ci-cd-setup-integration-jira/#technical-notes","title":"Technical notes","text":"

This integration use the following variables, that must be available from the pipelines:

  • JIRA_HOST
  • JIRA_EMAIL
  • JIRA_TOKEN
  • JIRA_PAT
"},{"location":"salesforce-ci-cd-setup-integration-ms-teams/","title":"Configure Microsoft Teams notifications from Salesforce CI/CD","text":""},{"location":"salesforce-ci-cd-setup-integration-ms-teams/#ms-teams-integration","title":"Ms Teams Integration","text":"

MS Teams Web Hooks have been deprecated my Microsoft so have been removed from sfdx-hardis.

Instead, please use Email Notifications with the Ms Teams Channel Email as NOTIF_EMAIL_ADDRESS

To get MsTeams email channel, click on the channel contextual menu, then \"Get channel E-mail Address\"

Then make sure that anyone can send emails to the channel by selecting the first option

"},{"location":"salesforce-ci-cd-setup-integration-slack/","title":"Configure Integrations between sfdx-hardis and Slack","text":""},{"location":"salesforce-ci-cd-setup-integration-slack/#slack-integration","title":"Slack Integration","text":"

You can receive notifications on slack channels when sfdx-hardis events are happening:

  • Deployment from a major branch to a major Salesforce org (ex: integration git branch to Integration Org)
  • Salesforce Org Monitoring
    • Latest updates
    • Failing apex tests
    • Monitoring checks notifications

"},{"location":"salesforce-ci-cd-setup-integration-slack/#configure-slack-application","title":"Configure Slack Application","text":"

All the following steps are summarized in this video tutorial

"},{"location":"salesforce-ci-cd-setup-integration-slack/#create-slack-app","title":"Create slack app","text":"

Process only if a sfdx-hardis bot has not yet been configured on your slack. Otherwise, just request the slack token value to your slack administrator

Create a slack app here -> https://api.slack.com/apps

  • Name it sfdx-hardis bot or any nickname you like, like your guinea pig name !
  • Go to permissions and add the following scopes
    • chat-write
    • chat-write.customize
    • chat-write.public
  • Create auth token and copy its values
"},{"location":"salesforce-ci-cd-setup-integration-slack/#configure-sfdx-hardis-for-slack","title":"Configure sfdx-hardis for slack","text":"
  • Create a secret value named SLACK_TOKEN with auth token value in your Git provider configuration
  • Create a slack channel that will receive all notifications (ex: #notifs-sfdx-hardis)
  • Open the channel info, copy its ID and create a secret value named SLACK_CHANNEL_ID in your git provider configuration
  • Invite the sfdx-hardis bot user to the channel (ex: /invite @sfdx-hardis-bot)
  • Additionally, you can create branch-scoped channels by creating new channels and create appropriate variables
    • Example: Channel #notifs-sfdx-hardis-integration and variable SLACK_CHANNEL_ID_INTEGRATION
  • You can also define an additional channel to receive only warning, error and critical notifications in another channel
    • Example: Channel #notifs-monitor-hot and variable SLACK_CHANNEL_ID_ERRORS_WARNINGS
  • Make sure all those variables are visible to your CI/CD pipelines

That's all, you're all set !

"},{"location":"salesforce-ci-cd-setup-integrations-home/","title":"Configure Integrations between sfdx-hardis and external tools","text":"

Every info that sfdx-hardis can provide is available in log files or console terminals.

In order to enhance the user experience, integrations with external tools must be configured.

"},{"location":"salesforce-ci-cd-setup-integrations-home/#git-providers","title":"Git Providers","text":"

Depending of your git provider, configure one of the following integrations.

  • GitHub
    • Deployment status in Merge Request notes
    • Quick Deploy to enhance performances
  • Gitlab
    • Deployment status in Merge Request notes
    • Quick Deploy to enhance performances
  • Azure Pipelines
    • Deployment status in Pull Request threads
    • Quick Deploy to enhance performances
  • BitBucket
    • Deployment status in Pull Request comments
    • Quick Deploy to enhance performance
"},{"location":"salesforce-ci-cd-setup-integrations-home/#message-notifications","title":"Message notifications","text":"
  • Slack
    • Notifications
  • Microsoft Teams
    • Notifications
  • Email
    • Notifications
  • API (ex: Grafana)
    • Notifications
"},{"location":"salesforce-ci-cd-setup-integrations-home/#ticketing-providers","title":"Ticketing providers","text":"
  • Jira
    • Enrich MR/PR comments by adding tickets references and links
    • Enrich notifications comments by adding tickets references and links
    • Post a comment and a label on JIRA issues when they are deployed in a major org
  • Azure Boards
    • Enrich MR/PR comments by adding work items references and links
    • Enrich notifications comments by adding work items references and links
    • Post a comment and a tag on Azure Work Items when they are deployed in a major org
  • Generic ticketing
    • Enrich MR/PR comments by adding tickets references and links
    • Enrich notifications comments by adding tickets references and links
"},{"location":"salesforce-ci-cd-setup-merge-request/","title":"First merge request","text":"
  • Initialization merge request
  • Common issues
    • Translations
"},{"location":"salesforce-ci-cd-setup-merge-request/#initialization-merge-request","title":"Initialization merge request","text":"

Create your first merge request with branch cicd as source, and your lower major branch as target (usually integration)

Make sure that before merging your first merge request, file manifest/destructiveChange.xml is empty

You will see errors, but it is normal: Follow Maintainer Guide to complete your configuration !

Once all controlling jobs are in success, your CI/CD setup is completed !

"},{"location":"salesforce-ci-cd-setup-merge-request/#common-issues","title":"Common issues","text":""},{"location":"salesforce-ci-cd-setup-merge-request/#translations","title":"Translations","text":"

If you removed Dashboards and reports from the repo, their translations can remain in files like translations/en_US.xml

Remove all related XML blocks as they contain unused translations.

"},{"location":"salesforce-ci-cd-solve-deployment-errors/","title":"Solve Salesforce deployment errors","text":"
  • Metadata errors
    • Fix with new commit
    • Fix with reset commits then new commit
  • Test classes errors
  • Code Coverage errors
  • SOS, I'm lost
"},{"location":"salesforce-ci-cd-solve-deployment-errors/#metadata-errors","title":"Metadata errors","text":"

sfdx-hardis will display the error and often provide tips about how to solve the error.

"},{"location":"salesforce-ci-cd-solve-deployment-errors/#fix-with-new-commit","title":"Fix with new commit","text":"

You can solve the issue, create a new commit and run again command

"},{"location":"salesforce-ci-cd-solve-deployment-errors/#fix-with-reset-commits-then-new-commit","title":"Fix with reset commits then new commit","text":"

If the issue is caused by the fact that you committed files that you finally decided to not publish, you can reset your selection.

  • Click on : that will rollback all the previous commits of your current git branch
  • Stage and commit again the elements that you want to publish
  • Run command
"},{"location":"salesforce-ci-cd-solve-deployment-errors/#test-classes-errors","title":"Test classes errors","text":"

That's simple: fix the test classes :)

If you are an admin, you might need the help of a developer, who will directly work in your branch

"},{"location":"salesforce-ci-cd-solve-deployment-errors/#code-coverage-errors","title":"Code Coverage errors","text":"

Don't be lazy, write the missing test classes :)

You know you'll need them to be able to deploy in production anyway :)

"},{"location":"salesforce-ci-cd-solve-deployment-errors/#sos-im-lost","title":"SOS, I'm lost","text":"
  • Call your release manager, he/she's here to help you !
  • Google / ChatGPT / Bard the issue
  • Ask on Slack #inte-hotline-cicd if you work at Cloudity
  • Ask on Salesforce StackExchange
"},{"location":"salesforce-ci-cd-solve-megalinter-errors/","title":"Solve Salesforce MegaLinter errors","text":"
  • Apex best practices using PMD
  • LWC best practices using eslint
  • Security issues
  • Excessive copy-pastes
  • Example of .mega-linter.yml config file
"},{"location":"salesforce-ci-cd-solve-megalinter-errors/#apex-best-practices-using-pmd","title":"Apex best practices using PMD","text":"

You don't want technical debt on your project !

Download job artifacts that will contain a file sfdx-scanner-report-apex.csv.

Open the file to see the errors

  • If the errors are in code that has been written by a developer, solve it
  • If the errors are from imported or generated classes, you can bypass them by adding annotation @SuppressWarnings('PMD') at the top of the classes
  • // NOPMD at the end of a line will make an issue ignored, but again use it only in case of false positive, never to \"Publish more quickly\", else you'll create technical debt.
    • If you use // NOPMD, specify why as comment . Example: // NOPMD Strings already escaped before
"},{"location":"salesforce-ci-cd-solve-megalinter-errors/#lwc-best-practices-using-eslint","title":"LWC best practices using eslint","text":"

sfdx-scanner-lwc embedded in MegaLinter is hard to use.

If you don't succeed, you can define SALESFORCE_SFDX_SCANNER_LWC in DISABLE_LINTERS property in .mega-linter.yml config file.

"},{"location":"salesforce-ci-cd-solve-megalinter-errors/#security-issues","title":"Security issues","text":"

Solve the security issues if they are critical like hardcoded tokens, or bypass the linters (release manager action only)

"},{"location":"salesforce-ci-cd-solve-megalinter-errors/#excessive-copy-pastes","title":"Excessive copy-pastes","text":"

Refactor your code to avoid excessive copy-pastes !

You can also add exceptions in .jscpd.json file, but really in case it has sense, not out of laziness

"},{"location":"salesforce-ci-cd-solve-megalinter-errors/#example-of-mega-linteryml-config-file","title":"Example of .mega-linter.yml config file","text":"
# Extend from shared sfdx-hardis Mega-Linter configuration :)\nEXTENDS:\n  - https://raw.githubusercontent.com/hardisgroupcom/sfdx-hardis/main/config/sfdx-hardis.mega-linter-config.yml\n\nDISABLE_LINTERS:\n- SALESFORCE_SFDX_SCANNER_LWC\n- SALESFORCE_SFDX_SCANNER_AURA\n- CSS_STYLELINT\n\nSALESFORCE_SFDX_SCANNER_APEX_DISABLE_ERRORS_IF_LESS_THAN: 6 # ONLY THE RELEASE MANAGER CAN UPDATE THIS VALUE !\n
"},{"location":"salesforce-ci-cd-use-home/","title":"Salesforce CI/CD Contributor Guide","text":"
  • Initialization
  • Make updates on your Salesforce project
"},{"location":"salesforce-ci-cd-use-home/#initialization","title":"Initialization","text":"

You need a stack of applications and to have Salesforce sources on your computer to be able to start to work on a CI/CD project.

  • Install necessary applications on your computer (to perform only once by computer)
  • Clone git repository on your computer (to perform only once by Salesforce project)
"},{"location":"salesforce-ci-cd-use-home/#make-updates-on-your-salesforce-project","title":"Make updates on your Salesforce project","text":"

Now your computer is ready, let's see how you can use sandboxes or scratch orgs to make updates in your Salesforce projects !

  • Create a new task
  • Work on your current task
  • Publish your task (by creating a Merge Request)
  • Handle merge requests errors
  • Validate a merge request (Release manager and advanced user only, depending on the project organization)
"},{"location":"salesforce-ci-cd-use-install/","title":"Salesforce CI/CD Installation User guide","text":""},{"location":"salesforce-ci-cd-use-install/#computer-installation-user-guide","title":"Computer Installation user guide","text":"

If you installed Salesforce DX or Salesforce CLI using Windows installer, please uninstall it using Windows -> Programs > Uninstall

See tutorial

  • Install Visual Studio code
  • Install VsCode extension VsCode SFDX Hardis by searching for Hardis is VsCode extensions plugin pane.
  • Once installed, click on in VsCode left bar
  • Messages will appear at the bottom right of VsCode and ask you to install additional applications and activate settings. Follow all of them until there is none left.
    • When later you'll see such messages again from sfdx-hardis, click to apply them to upgrade applications.

  • When no warning in displayed in the dependencies panel, you're all set !

Under the hood

The installed applications are the following:

  • Git
  • Node.js
  • Salesforce CLI
  • Salesforce DX plugins
    • sfdx-hardis
    • Salesforce Data Move Utility
    • SFDX Git Delta
    • Texei Sfdx Plugin

Now your computer is all set, you can clone your project git repository :)

"},{"location":"salesforce-ci-cd-validate-merge-request/","title":"Validate a merge request on a Salesforce CI/CD project","text":"
  • Conflicts
  • Control jobs
    • Check deploy job
    • Code Quality job
  • Merge the Pull Request / Merge Request
    • Pre-deployment actions
    • Effective merge
    • Post-deployment actions
"},{"location":"salesforce-ci-cd-validate-merge-request/#conflicts","title":"Conflicts","text":"

This section must be managed by team members with git knowledge

If elements has been modified in another branch, you need to manage conflicts before being able to merge.

  • Merge conflicts then commit and push your updates, it will trigger again the control job with the new branch state.

This video shows how to merge conflicts with Visual Studio Code.

In case conflicts are too complicated to manage (like on a Flow for example), you need to:

  • Retrofit the new version of the flow in your branch (that will overwrite your updates)
  • Sfdx Push it to your source-tracked sandbox or scratch org
  • Make again the updates in the Salesforce Setup
  • Sfdx Pull the updated version in your local branch
  • Git Commit & Push to your branch
"},{"location":"salesforce-ci-cd-validate-merge-request/#control-jobs","title":"Control jobs","text":"

Each merge request runs automatically the control jobs that will insure that the future deployment with be valid.

"},{"location":"salesforce-ci-cd-validate-merge-request/#check-deploy-job","title":"Check deploy job","text":"

See Handle Deployment errors

"},{"location":"salesforce-ci-cd-validate-merge-request/#code-quality-job","title":"Code Quality job","text":"

See Handle MegaLinter errors

"},{"location":"salesforce-ci-cd-validate-merge-request/#merge","title":"Merge","text":"

Depending on the project organization, this action can be allowed only to Release managers, or to more team members

If there are no conflicts and if all control jobs are in success, you can proceed to the merge of the merge request.

"},{"location":"salesforce-ci-cd-validate-merge-request/#pre-deployment-actions","title":"Pre deployment actions","text":"

If pre-deployment actions are required, perform them before clicking on the button to merge the Merge Request / Pull Request

Pre-deployment actions can usually be found in README.md

IMPORTANT: If Custom Profiles are deployed for the first time, you MUST create them manually in target org, by cloning them from \"Minimal access\" Profile

"},{"location":"salesforce-ci-cd-validate-merge-request/#effective-merge","title":"Effective merge","text":"
  • Click on Merge
    • If the merge request is from a minor branch (dev or config task), make sure that Squash commits and Delete after merge are checked
    • If the merge request if from a major branch (develop, recette, uat, preprod...), make sure that Squash commits and Delete after merge are NOT checked
  • The merge commit in the target branch will trigger a new job that will automatically deploy the updated source to the corresponding Salesforce org
"},{"location":"salesforce-ci-cd-validate-merge-request/#post-deployment-actions","title":"Post deployment actions","text":"

If post-deployment actions are required, perform them before clicking on the button to merge the Merge Request / Pull Request

Post-deployment actions can usually be found in README.md

"},{"location":"salesforce-ci-cd-work-on-task-configuration/","title":"Perform configuration in your Salesforce org","text":"
  • Configuration
    • Api names
    • Access management
    • Flows
    • Hardcoded Ids
    • Images
    • User references
"},{"location":"salesforce-ci-cd-work-on-task-configuration/#configuration","title":"Configuration","text":"

Please follow as much as possible these recommendations when you work on a CI/CD Salesforce project, otherwise it will generate more release management charges and risks of regressions.

"},{"location":"salesforce-ci-cd-work-on-task-configuration/#api-names","title":"Api names","text":"
  • Do not rename API names (field names, picklist values, pages...)
  • Do not prefix API Names with numbers: Git provides historization of updates, so it's better to have elements sorted by alphabetical order than by order of creation
  • Do not change the type of custom fields: It forces the release manager to perform manual actions
"},{"location":"salesforce-ci-cd-work-on-task-configuration/#access-management","title":"Access management","text":"
  • Always use Permission Sets instead of Profiles. If you need profiles, discuss with your release manager.
  • If you create a Custom Profile, please notify your release manager.
    • Before the first deployment, this Profile must be created manually in the target org by cloning \"Minimum access\" Profile
"},{"location":"salesforce-ci-cd-work-on-task-configuration/#flows","title":"Flows","text":"
  • If you need to update Flows, discuss to make sure that no other member of the team is updating the same Flow in another branch/org
    • If it happens, conflicts are not manageable so one of you will later need to perform the updates again
"},{"location":"salesforce-ci-cd-work-on-task-configuration/#hardcoded-ids","title":"Hardcoded Ids","text":"
  • Never use hardcoded Ids in Flows and Formulas (or anywhere else)
"},{"location":"salesforce-ci-cd-work-on-task-configuration/#images","title":"Images","text":"
  • Use static resources or content assets to store images
"},{"location":"salesforce-ci-cd-work-on-task-configuration/#user-references","title":"User references","text":"
  • Do not use direct references to users, use Public Groups instead
  • Share your reports and email templates with public groups, not named users.
"},{"location":"salesforce-ci-cd-work-on-task-development/","title":"Develop on a Salesforce DX project","text":""},{"location":"salesforce-ci-cd-work-on-task-development/#salesforce-development","title":"Salesforce Development","text":""},{"location":"salesforce-ci-cd-work-on-task-development/#update-code-xml-metadatas","title":"Update code & XML Metadatas","text":"
  • You can update code and XML metadatas using VsCode IDE
  • When you need to upload the updates to your org, use command
  • If you made updates directly on your org, use command to retrieve into local files the updates that you performed online with point & click
  • Once you have finished, you can publish your task
"},{"location":"salesforce-ci-cd-work-on-task-development/#recommendations","title":"Recommendations","text":"
  • Use Visual Studio code editor to update code (online Developer Console is not recommended)
"},{"location":"salesforce-ci-cd-work-on-task-install-packages/","title":"Install packages on your org","text":""},{"location":"salesforce-ci-cd-work-on-task-install-packages/#install-packages","title":"Install packages","text":"

Packages (managed or not) must never be directly installed in a major org (integration, uat, preprod, production), it has to be done in dev sandbox / scratch orgs

If you can find the package id (starting by 04T), use sfdx-hardis command to install package instead of installing them directly with the URL

If you installed a package using an URL, use command Retrieve packages button to retrieve package config before creating your merge request (be careful of what you commit in .sfdx-hardis.yml file !)

Once packages are referenced in .sfdx-hardis.yml, they will automatically be installed on major orgs during CI/CD deployments

"},{"location":"salesforce-ci-cd-work-on-task-open-org/","title":"Open your Salesforce org","text":""},{"location":"salesforce-ci-cd-work-on-task-open-org/#open-your-org","title":"Open your org","text":"

You can use Salesforce Setup to configure your org as you would do on any sandbox.

  • Open your Salesforce DX project with Visual Studio Code
  • Open VsCode SFDX Hardis extension by clicking on in VsCode left bar (loading can task several seconds)
  • Click on to open your org in browser
    • If you want to use another org, use menu to select another one
  • Perform your configurations in the org
  • Once you have finished, you can publish your task
"},{"location":"salesforce-ci-cd-work-on-task-profiles/","title":"Handle Profiles on a Salesforce CI/CD project","text":""},{"location":"salesforce-ci-cd-work-on-task-profiles/#deploy-profiles","title":"Deploy Profiles","text":""},{"location":"salesforce-ci-cd-work-on-task-profiles/#use-permission-sets","title":"Use Permission Sets","text":"

In case an attribute is available on Profiles and Permission Sets: USE PERMISSION SETS :)

  • Apex Class Access (classAccesses)
  • Custom Metadata Type Access (customMetadataTypeAccesses)
  • External Data Source Access (externalDataSourceAccesses)
  • Field Permissions (fieldPermissions)
  • Object Permissions (objectPermissions)
  • Page Access (pageAccesses)
  • User Permissions (userPermissions (except on Admin Profile))

If you are on a build project, it is recommended to automate Minimize Profile so such attributes are automatically removed from Profiles before Merge Requests.

"},{"location":"salesforce-ci-cd-work-on-task-profiles/#tab-visibility","title":"Tab visibility","text":"

When you retrieve a profile, standard tabs visibility is not present in the XML.

This is quite boring because if you do nothing, Calendar, Tasks, Home or Contact tab visibilities won't be deployed !

To avoid that, standard tab visibility must be added in the Profile XML.

You can use sfdx-hardis command Fix Profile Tabs to Show / Hide tabs in your Profile XML files.

"},{"location":"salesforce-ci-cd-work-on-task/","title":"Work on a task on a Salesforce DX project","text":""},{"location":"salesforce-ci-cd-work-on-task/#work-on-a-cicd-project","title":"Work on a CI/CD project","text":"
  • Open your org

There are a set of recommended rules to follow to help the Release Management to be as fluid as possible

  • Guidelines for Salesforce configuration
  • Guidelines for Profiles & Permissions Sets
  • Guidelines for Package installation
  • Guidelines for Salesforce Development
"},{"location":"salesforce-deployment-assistant-error-list/","title":"Sfdx-hardis deployment assistant list of errors","text":""},{"location":"salesforce-deployment-assistant-error-list/#salesforce-deployment-assistant-errors-list","title":"Salesforce deployment assistant errors list","text":"

sfdx-hardis can help solve solve deployment errors using a predefined list of issues and associated solutions

See how to setup sfdx-hardis deployment assistant

If you see a deployment error which is not here yet, please add it in this file :)

"},{"location":"salesforce-deployment-assistant-error-list/#api-version-error","title":"API Version error","text":"

Detection

  • RegExp: Error (.*) The (.*) apiVersion can't be \"([0-9]+)\"

Resolution

{1} metadata has probably been created/updated in a sandbox already upgraded to next platform version (ex: Sandbox in Summer'23 and Production in Spring'23)\n- First, try to update the api version in the XML of {1} metadata file (decrement the number in <apiVersion>{3}.0</apiVersion>)\n- If it still doesn't work because the metadata structure has changed between version, you may try a sf project:retrieve:start of the metadata by forcing --api-version at the end of the command.\n
"},{"location":"salesforce-deployment-assistant-error-list/#allow-deployment-with-pending-apex-jobs","title":"Allow deployment with pending Apex Jobs","text":"

Detection

  • String: You can bypass this error by allowing deployments with Apex jobs in the Deployment Settings page in Setup.

Resolution

Go to target org, in Setup -> Deployment Settings -> Activate option \"Allow deployments of components when corresponding Apex jobs are pending or in progress.\"\n
"},{"location":"salesforce-deployment-assistant-error-list/#can-not-change-field-type-to-a-formula-field","title":"Can not change field type to a formula field","text":"

Detection

  • RegExp: Error (.*) Cannot update a field from a Formula to something else

Resolution

You need to manually delete or rename the field in the target org to allow the deployment to pass\n- First, try to manually delete field {1} in the target org\n- if you can't delete {1}, rename it into {1}_ToDel, then once the deployment done, delete {1}_ToDel\n
"},{"location":"salesforce-deployment-assistant-error-list/#can-not-change-type-due-to-existing-data","title":"Can not change type due to existing data","text":"

Detection

  • RegExp: Error (.*) Cannot change type due to existing data

Resolution

It is usually not recommended to change types of fields, but if it's really necessary you can:\n- Manually change the type of {1} in the target org\n- If you can't manually change the type:\n  - you may modify the dependencies (Formulas, Flows...) using {1}, so they don't use this field\n  - you can also delete dependencies (Formulas, Flows...) using {1}, but make sure they are deployed again later\n- More help: https://help.salesforce.com/s/articleView?id=000327186&type=1\n
"},{"location":"salesforce-deployment-assistant-error-list/#can-not-change-field-type-with-picklist","title":"Can not change field type with picklist","text":"

Detection

  • RegExp: Error (.*) Cannot change which global value set this picklist uses

Resolution

You probably updated the type of field {1}, and Salesforce does not allows that with deployments. You can:\n- Try to manually change the type of {1} directly in target org, but it may not be technically possible\n- Delete field {1} in target org: it will be recreated after deployment (but you will loose data on existing records, so be careful if your target is a production org)\n- Create another field with desired type and manage data recovery if the target is a production org\n
"},{"location":"salesforce-deployment-assistant-error-list/#can-not-delete-custom-field","title":"Can not delete custom field","text":"

Detection

  • RegExp: This (.*) is referenced elsewhere in salesforce.com
  • RegExp: Le champ personnalis\u00e9 (.*) est utilis\u00e9 dans (.*)

Resolution

Custom field {1} can not be deleted because it is used elsewhere. Remove its references ans try again\nTHIS MAY BE A FALSE POSITIVE if you are just testing the deployment, as destructiveChanges are deployed separately from updated items deployment check\n
"},{"location":"salesforce-deployment-assistant-error-list/#can-not-delete-record-type","title":"Can not delete record type","text":"

Detection

  • RegExp: Error (.*) Cannot delete record type through API

Resolution

You need to manually delete record type {1} in target org\n- Edit record type {1}, uncheck \"Active\"\n- Delete record type {1}\n
"},{"location":"salesforce-deployment-assistant-error-list/#can-not-find-folder","title":"Can not find folder","text":"

Detection

  • RegExp: Error (.*) Cannot find folder:(.*)

Resolution

Folder {2} is missing.\n- If folder {2} is existing in sources, add it in related package.xml\n- If folder {2} is not existing in DX sources, please use sf hardis:project:clean:retrievefolders to retrieve it\n- If both previous solutions did not work, go create manually folder {2} in target org\n
"},{"location":"salesforce-deployment-assistant-error-list/#can-not-find-user","title":"Can not find user","text":"

Detection

  • RegExp: Error (.*) Cannot find a user that matches any of the following usernames

Resolution

You made reference to username(s) in {1}, and those users probably do not exist in target org.\n- Do not use named users, but user public groups for assignments -> https://help.salesforce.com/s/articleView?id=sf.creating_and_editing_groups.htm&type=5\n- or Create matching user(s) in the target deployment org\n- or Remove the XML part referring to hardcoded usernames\n\nExample of XML you have to remove in {1}:\n\n<folderShares>\n  <accessLevel>Manage</accessLevel>\n  <sharedTo>nicolas.vuillamy@hardis-scratch-po-tgci-root-develop_20220412_0604.com</sharedTo>\n  <sharedToType>User</sharedToType>\n</folderShares>\n
"},{"location":"salesforce-deployment-assistant-error-list/#can-not-find-user-2","title":"Can not find user (2)","text":"

Detection

  • RegExp: Error (.*) In field: (.*) - no User named (.*) found

Resolution

You made reference to username {3} in {1}, and it probably does not exist in the target org.\n- Do not use named users, but user public groups for assignments -> https://help.salesforce.com/s/articleView?id=sf.creating_and_editing_groups.htm&type=5\n- or Create matching user {3} in the target deployment org\n- or open {1} metadata and remove the XML part referring to hardcoded username {3}\n
"},{"location":"salesforce-deployment-assistant-error-list/#cannot-update-a-field-to-a-summary-from-something-else","title":"Cannot update a field to a Summary from something else","text":"

Detection

  • RegExp: Error (.*) Cannot update a field to a (.*) from something else

Resolution

You probably updated the type of field {1} to type {2}, and Salesforce does not allows that with deployments. You can:\n- Try to manually change the type of {1} directly in target org, but it may not be technically possible\n- Delete field {1} in target org: it will be recreated after deployment (but you will loose data on existing records, so be careful if your target is a production org)\n- Create another field with desired type and manage data recovery if the target is a production org\n
"},{"location":"salesforce-deployment-assistant-error-list/#change-matching-rule","title":"Change Matching Rule","text":"

Detection

  • RegExp: Error (.*) Before you change a matching rule, you must deactivate it

Resolution

To be able to deploy, you must go in target org setup to manually deactivate matching rule {1}\n
"},{"location":"salesforce-deployment-assistant-error-list/#condition-missing-reference","title":"Condition missing reference","text":"

Detection

  • RegExp: Error (.*) field integrity exception: unknown \\(A condition has a reference to (.*), which doesn't exist.\\)

Resolution

There is a reference to {2} in {1}, and {2} is not found. You can either:\n- Add {2} in your deployment sources and make sure it is named in package.xml\n- Remove the reference to {2} in {1}\n
"},{"location":"salesforce-deployment-assistant-error-list/#couldnt-retrieve-or-load-information-on-the-field","title":"Couldn't retrieve or load information on the field","text":"

Detection

  • RegExp: Error (.*) Something went wrong. We couldn't retrieve or load the information on the field: (.*)\\.

Resolution

There is a reference to {2} in {1}, and {2} is not found. You can either:\n- Commit {2} in your deployment sources and make sure it is named in package.xml\n- Remove the reference to {2} in {1}\n
"},{"location":"salesforce-deployment-assistant-error-list/#custom-object-not-found","title":"Custom object not found","text":"

Detection

  • RegExp: Error (.*) In field: field - no CustomObject named (.*) found

Resolution

A reference to a custom object {2} is not found in {1}:\n- If you renamed the custom object, do a search/replace in sources with previous object name and new object name\n- If you deleted the custom object, or if you don't want to deploy it, do a search on the custom object name, and remove XML elements referencing it\n- If the object should exist, make sure it is in force-app/main/default/objects and that the object name is in manifest/package.xml in CustomObject section\nYou may also have a look to command sf hardis:project:clean:references\n
"},{"location":"salesforce-deployment-assistant-error-list/#custom-field-not-found","title":"Custom field not found","text":"

Detection

  • RegExp: Error (.*) In field: (.*) - no CustomField named (.*)\\.(.*) found

Examples

  • Error PS_Admin In field: field - no CustomField named User.expcloud__Portal_Username__c found

Resolution

A reference to a custom field {3}.{4} is not found in {1}:\n- If you renamed {3}.{4}, do a search/replace in {1} with previous field name and {4}\n- If you deleted {3}.{4}, or if you don't want to deploy it, do a search on {4} in all sources, and remove all XML elements referring to {3}.{4} (except in destructiveChanges.xml)\n- If {3}.{4} should exist, make sure it is in force-app/main/default/objects/{3}/fields and that {3}.{4} is in manifest/package.xml in CustomField section\n- If {3}.{4} is standard, the error is because {3}.{4} is not available in the org you are trying to deploy to. You can:\n  - Remove the reference to {4} in the XML of {1} ( maybe sf hardis:project:clean:references can clean automatically for you ! )\n  - Activate the required features/license in the target org\n
"},{"location":"salesforce-deployment-assistant-error-list/#mandatory-custom-field-can-not-be-in-a-profilepermission-set","title":"Mandatory custom field can not be in a profile/permission set","text":"

Detection

  • RegExp: Error (.*) You cannot deploy to a required field: (.*)

Resolution

- Search for {2} in source file XML of {1}, then remove the entries matching the results\nExample of element to delete:\n<fieldPermissions>\n  <editable>true</editable>\n  <field>{2}</field>\n  <readable>true</readable>\n</fieldPermissions>\n
"},{"location":"salesforce-deployment-assistant-error-list/#custom-metadata-entry-not-found","title":"Custom metadata entry not found","text":"

Detection

  • RegExp: Error (.*) In field: (.*) - no CustomMetadata named (.*) found

Resolution

A reference to a custom metadata {3} of type {2} is not found in {1}:\n- Are you sure you deployed {3} ?\n- If you use a package.xml, is {3} present within type CustomMetadata ?\n
"},{"location":"salesforce-deployment-assistant-error-list/#expired-access-refresh-token","title":"Expired Access / Refresh Token","text":"

Detection

  • String: expired access/refresh token

Resolution

Run command \"Select another org\" from Status panel (or sf hardis:org:select) to authenticate again to your org\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-data-category-group","title":"Missing Data Category Group","text":"

Detection

  • RegExp: Error (.*) In field: DeveloperName - no DataCategoryGroup named (.*) found

Resolution

If Data Category Group {2} is not existing yet in target org, you might need to:\n- create it manually in target org before deployment\n- comment DataCategoryGroup in {1} XML\n
"},{"location":"salesforce-deployment-assistant-error-list/#dependent-class-is-invalid-and-needs-recompilation","title":"Dependent class is invalid and needs recompilation","text":"

Detection

  • RegExp: Error (.*) Dependent class is invalid and needs recompilation

Resolution

Solve the other errors and this one will disappear !\n
"},{"location":"salesforce-deployment-assistant-error-list/#duplicate-value-platform-action-id-list","title":"Duplicate value Platform Action Id List","text":"

Detection

  • String: duplicate value found: PlatformActionListId duplicates value on record with id

Resolution

There are probably issue with conflict management. Open the XML of the source item, and replace all <sortOrder> numbers to make an ascending order, starting with 0\n
"},{"location":"salesforce-deployment-assistant-error-list/#duplicate-label","title":"Duplicate label","text":"

Detection

  • RegExp: Error (.*) Duplicate label: (.*)

Resolution

You probably renamed the picklist API name for {2}. Please update manually the picklist {1} in the target org to avoid to have a duplicate label\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-e-mail-template","title":"Missing e-mail template","text":"

Detection

  • RegExp: In field: template - no EmailTemplate named (.*) found

Resolution

An email template should be present in the sources. To retrieve it, you can run:\nsf project retrieve start -m EmailTemplate:{1} -o YOUR_ORG_USERNAME\n
"},{"location":"salesforce-deployment-assistant-error-list/#empty-source-items","title":"Empty source items","text":"

Detection

  • String: Required field is missing: sharingOwnerRules
  • String: Required field is missing: standardValue
  • String: Required field is missing: valueTranslation

Resolution

You probably retrieved empty items, that must not be included within the SFDX project\nTo remove them, please run sfdx:hardis:project:clean:emptyitems\n
"},{"location":"salesforce-deployment-assistant-error-list/#enable-crm-analytics","title":"Enable CRM Analytics","text":"

Detection

  • String: It should be created by enabling the CRM Analytics Cloud preference

Resolution

You must enable CRM Analytics (ex Wave, Einstein Analytics & Tableau CRM) in the target org.\nYou probably also need to add CRM Analytics Admin Permission Set assignment to the deployment user\n
"},{"location":"salesforce-deployment-assistant-error-list/#error-parsing-file","title":"Error parsing file","text":"

Detection

  • RegExp: Error (.*) Error parsing file: (.*)

Resolution

There has been an error parsing the XML file of {1}: {2}\n- Open file {1} and look where the error can be ! (merge issue, typo, XML tag not closed...)\n
"},{"location":"salesforce-deployment-assistant-error-list/#formula-picklist-field-issue","title":"Formula picklist field issue","text":"

Detection

  • RegExp: Field:(.*) must not be Required

Resolution

You probably made read only field {1} that was required before.\nFind field {1} in the layout source XML, then replace Required by Readonly\n
"},{"location":"salesforce-deployment-assistant-error-list/#field-not-available-for-element","title":"Field not available for element","text":"

Detection

  • RegExp: Field (.*) is not available for

Resolution

You probably changed the type of field {1}.\nFind field {1} in the source XML, and remove the section using it\n
"},{"location":"salesforce-deployment-assistant-error-list/#formula-picklist-field-issue_1","title":"Formula picklist field issue","text":"

Detection

  • String: Les champs de liste de s\u00e9lection sont pris en charge uniquement dans certaines fonctions.

Resolution

You probably changed the type of a field that is used in a formula.\nUpdate the formula to use a field compliant with formulas.\nMore details at https://help.salesforce.com/articleView?id=sf.tips_on_building_formulas.htm&type=5\n
"},{"location":"salesforce-deployment-assistant-error-list/#flow-must-be-deleted-manually","title":"Flow must be deleted manually","text":"

Detection

  • RegExp: .flow (.*) insufficient access rights on cross-reference id

Resolution

Flow {1} can not be deleted using deployments, please delete it manually in the target org using menu Setup -> Flows , context menu on {1} -> View details and versions -> Deactivate all versions -> Delete flow\n
"},{"location":"salesforce-deployment-assistant-error-list/#insufficient-access-rights-on-cross-reference-id","title":"Insufficient access rights on cross-reference id","text":"

Detection

  • RegExp: Error (.*) insufficient access rights on cross-reference id

Resolution

- If {1} is a Flow, it can not be deleted using deployments, please delete it manually in the target org using menu Setup -> Flows , context menu on {1} -> View details and versions -> Deactivate all versions -> Delete flow\n- If you changed a custom field from unique to not unique, you need to manually make the change in the target org\n
"},{"location":"salesforce-deployment-assistant-error-list/#invalid-formula-grouping-context","title":"Invalid formula grouping context","text":"

Detection

  • String: Invalid custom summary formula definition: You must select a grouping context to use any report summary function

Resolution

You need to update your Report definition. See workaround here -> https://salesforce.stackexchange.com/questions/294850/grouping-error-with-prevgroupval-function\n
"},{"location":"salesforce-deployment-assistant-error-list/#invalid-report-type","title":"Invalid report type","text":"

Detection

  • RegExp: Error (.*) invalid report type

Resolution

Report type is missing for report {1}\n- Open report {1} to se what report type is used\n- Retrieve the report type from an org and add it to the sfdx sources\n
"},{"location":"salesforce-deployment-assistant-error-list/#invalid-scopemine-not-allowed","title":"Invalid scope:Mine, not allowed","text":"

Detection

  • String: Invalid scope:Mine, not allowed

Resolution

Replace Mine by Everything in the list view SFDX source XML.\nHave a look at this command to manage that automatically :)\nhttps://sfdx-hardis.cloudity.com/hardis/org/fix/listviewmine/ \n
"},{"location":"salesforce-deployment-assistant-error-list/#invalid-field-in-related-list","title":"Invalid field in related list","text":"

Detection

  • RegExp: Error (.*) Invalid field:(.*) in related list:(.*)

Resolution

Field {2} is unknown. You can:\n- Activate the related feature license or option to make {2} existing in target org\n- Update XML of {1} to remove reference to field {2} in the related list {3}\n- Update XML of {1} to remove the whole related list {3}\nExample of XML to remove:\n<relatedLists>\n  <fields>SOLUTION.ISSUE</fields>\n  <fields>SOLUTION.SOLUTION_NUMBER</fields>\n  <fields>SOLUTION.STATUS</fields>\n  <fields>CORE.USERS.ALIAS</fields>\n  <relatedList>RelatedSolutionList</relatedList>\n</relatedLists>\n
"},{"location":"salesforce-deployment-assistant-error-list/#invalid-field-for-upsert","title":"Invalid field for upsert","text":"

Detection

  • RegExp: Error (.*) Invalid field for upsert, must be an External Id custom or standard indexed field: (.*) \\((.*)\\)

Resolution

You tried to use field {2} for an upsert call in {1}.\n- Is it declared as externalId ?\n- Is the customIndex source file present in the deployment ?\n- If it is declared as externalId and customIndex is present, you may have to go manually define the field as externalId in the target org\n
"},{"location":"salesforce-deployment-assistant-error-list/#invalid-type","title":"Invalid type","text":"

Detection

  • RegExp: Error (.*) Invalid type: (.*) \\((.*)\\)

Resolution

Apex error in {1} with unknown type {2} at position {3}. If {2} is a class name, try to fix it, or maybe it is missing in the files or in package.xml !\n
"},{"location":"salesforce-deployment-assistant-error-list/#campaign-can-not-be-updated","title":"Campaign can not be updated","text":"

Detection

  • String: The object \"Campaign\" can't be updated

Resolution

Add \"MarketingUser\" in project-scratch-def.json features\nIf it is already done, you may manually check \"MarketingUser\" field on the scratch org user\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-field-middlename","title":"Missing field MiddleName","text":"

Detection

  • String: field MiddleName
  • String: Variable does not exist: MiddleName

Resolution

MiddleNames must be activated in the target org.\n- Help: https://help.salesforce.com/articleView?id=000332623&type=1&mode=1\n- Scratch org setting:\n\"nameSettings\": {\n  \"enableMiddleName\": true\n}\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-field-suffix","title":"Missing field Suffix","text":"

Detection

  • String: field Suffix

Resolution

Suffix must be activated in the target org.\n- Help: https://help.salesforce.com/articleView?id=000332623&type=1&mode=1\n- Scratch org setting:\n\"nameSettings\": {\n  \"enableNameSuffix\": true\n},\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-field-syncedquoteid","title":"Missing field SyncedQuoteId","text":"

Detection

  • String: field SyncedQuoteId
  • String: Error force-app/main/default/objects/Quote/Quote.object-meta.xml
  • String: Error force-app/main/default/objects/Opportunity/fields/SyncedQuoteId.field-meta.xml

Resolution

Quotes must be activated in the target org.\n- Help: https://help.salesforce.com/articleView?id=sf.quotes_enable.htm&type=5\n- Scratch org setting:\n\"quoteSettings\": {\n  \"enableQuote\": true\n}\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-feature-contacttomultipleaccounts","title":"Missing feature ContactToMultipleAccounts","text":"

Detection

  • String: no CustomObject named AccountContactRelation found
  • String: Invalid field:ACCOUNT.NAME in related list:RelatedContactAccountRelationList

Resolution

Contacts to multiple accounts be activated in the target org.\n- Help: https://help.salesforce.com/articleView?id=sf.shared_contacts_set_up.htm&type=5\n- Scratch org setting:\n\"features\": [\"ContactsToMultipleAccounts\"]\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-feature-chatter-collaboration-group","title":"Missing feature Chatter Collaboration Group","text":"

Detection

  • String: CollaborationGroup

Resolution

Quotes must be activated in the target org.\n- Org: Setup -> Chatter settings -> Allow Records in Groups\n- Scratch org setting:\n\"chatterSettings\": {\n  \"allowRecordsInChatterGroup\": true\n},\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-feature-enhanced-notes","title":"Missing feature Enhanced notes","text":"

Detection

  • String: FeedItem.ContentNote

Resolution

Enhanced Notes must be activated in the target org.\n- Org: Setup -> Notes settings -> Enable Notes\n- Scratch org setting:\n\"enhancedNotesSettings\": {\n  \"enableEnhancedNotes\": true\n},\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-feature-ideas-notes","title":"Missing feature Ideas notes","text":"

Detection

  • String: Idea.InternalIdeasIdeaRecordType

Resolution

Ideas must be activated in the target org.\n- Org: https://help.salesforce.com/articleView?id=networks_enable_ideas.htm&type=0\n- Scratch org setting:\n\"ideasSettings\": {\n  \"enableIdeas\": true\n}\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-feature-live-agent","title":"Missing feature Live Agent","text":"

Detection

  • String: FeedItem.ContentNote

Resolution

Live Agent must be activated in the target org.\n- Org: Setup -> Live Agent Settings -> Enable Live Agent\n- Scratch org feature: LiveAgent\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-feature-product-request","title":"Missing feature Product Request","text":"

Detection

  • String: ProductRequest

Resolution

ProductRequest object is not available in the target org.\nMaybe you would like to clean its references within Profiles / PS using the following command ?\nsf hardis:project:clean:references , then select \"ProductRequest references\"\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-feature-social-customer-service","title":"Missing feature Social Customer Service","text":"

Detection

  • String: SocialPersona.AreWeFollowing

Resolution

Social Custom Service must be activated in the target org.\n- Org: Setup -> https://help.salesforce.com/articleView?id=sf.social_customer_service_setup_enable.htm&type=5\n- Scratch org feature: SocialCustomerService\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-feature-translation-workbench","title":"Missing feature Translation Workbench","text":"

Detection

  • RegExp: report-meta.xml(.*)filterlanguage

Resolution

Translation workbench must be activated in the target org.\n- Org: Setup -> https://help.salesforce.com/articleView?id=sf.customize_wbench.htm&type=5\n- Scratch org:\n\"languageSettings\": {\n  \"enableTranslationWorkbench\":  true,\n  \"enableEndUserLanguages\": true\n}\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-feature-opportunity-teams","title":"Missing feature Opportunity Teams","text":"

Detection

  • String: OpportunityTeam

Resolution

Opportunity Teams must be activated in the target org.\n- Org: Setup -> Opportunity Team Settings -> Enable Team Selling\n- Scratch org:\n\"opportunitySettings\": {\n  \"enableOpportunityTeam\": true\n}\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-feature-workcom","title":"Missing Feature Work.Com","text":"

Detection

  • String: WorkBadgeDefinition

Resolution

Work.com feature must be activated in the target org.\n- Org & Scratch: https://developer.salesforce.com/docs/atlas.en-us.workdotcom_dev_guide.meta/workdotcom_dev_guide/wdc_cc_setup_dev_org.htm\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-multi-currency-field","title":"Missing multi-currency field","text":"

Detection

  • RegExp: A reference to a custom field (.*)CurrencyIsoCode

Resolution

You probably need to activate MultiCurrency (from Setup -> Company information)\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-object-referenced-in-packagexml","title":"Missing object referenced in package.xml","text":"

Detection

  • RegExp: An object (.*) of type (.*) was named in package.xml, but was not found in zipped directory

Resolution

You can either:\n- Update the package.xml to remove the reference to the missing {2} {1}\n- Add the missing {2} {1} in your project source files\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-quick-action","title":"Missing Quick Action","text":"

Detection

  • RegExp: Error (.*) In field: QuickAction - no QuickAction named (.*) found

Resolution

QuickAction {2} referred in {1} is unknown. You can either:\n- Make sure your QuickAction {2} is present in source files and in package.xml\n- If {2} is a standard QuickAction, activate related feature in target org\n- Solve other errors that could impact QuickAction {2}\n- Remove QuickAction {2} in the source XML of {1}. Example of XML to remove below:\n<quickActionListItems>\n  <quickActionName>FeedItem.RypplePost</quickActionName>\n</quickActionListItems>\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-report","title":"Missing report","text":"

Detection

  • RegExp: Error (.*) The (.*) report chart has a problem with the \"reportName\" field

Resolution

{1} is referring to unknown report {2}. To retrieve it, you can run:\n- sf project retrieve start -m Report:{2} -o YOUR_ORG_USERNAME\n- If it fails, looks for the report folder and add it before report name to the retrieve command (ex: MYFOLDER/MYREPORTNAME)\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-sales-team","title":"Missing Sales Team","text":"

Detection

  • String: related list:RelatedAccountSalesTeam

Resolution

Account Teams must be activated in the target org.\n- Org: Setup -> Account Teams -> Enable\n- Scratch org setting:\n\"accountSettings\": {\n  \"enableAccountTeams\": true\n}\n}\n
"},{"location":"salesforce-deployment-assistant-error-list/#sharing-operation-already-in-progress","title":"sharing operation already in progress","text":"

Detection

  • String: sharing operation already in progress

Resolution

You can not deploy multiple SharingRules at the same time. You can either:\n- Remove SharingOwnerRules and SharingRule from package.xml (so it becomes a manual operation)\n- Use sf hardis:work:save to generate a deploymentPlan in .sfdx-hardis.json,\n- If you are trying to create a scratch org, add DeferSharingCalc in features in project-scratch-def.json\n
"},{"location":"salesforce-deployment-assistant-error-list/#network-issue","title":"Network issue","text":"

Detection

  • String: ECONNABORTED
  • String: ECONNRESET

Resolution

The network connection has been aborted, this is a purely technical issue.\nTry again, and if you still see errors, check the status of Salesforce instance on https://status.salesforce.com\n
"},{"location":"salesforce-deployment-assistant-error-list/#not-available-for-deploy-for-this-organization","title":"Not available for deploy for this organization","text":"

Detection

  • RegExp: Error (.*) Not available for deploy for this organization

Resolution

The user you use for deployments probably lacks of the rights (Profiles, Permission sets...) to manage {1}.\n- Assign the deployment user to the good Permission Sets, or modify its profile rights, then try again\n
"},{"location":"salesforce-deployment-assistant-error-list/#not-valid-sharing-model","title":"Not valid sharing model","text":"

Detection

  • RegExp: Error (.*) (.*) is not a valid sharing model for (.*) when (.*) sharing model is (.*)

Resolution

It seems that Sharing Models of {1} and {4} are not compatible in target org.\n- Use compatible sharing models between {1} and {4} by updating Sharing model of {1} or {4}\n- Make sure that sfdx sources {1}.object-meta.xml and {4}.object-meta.xml and in the files, and that {1} and {4} are in package.xml in CustomObject block\n- You may directly update sharingModel in XML. For example, replace <sharingModel>ReadWrite</sharingModel> by <sharingModel>Private</sharingModel> in {3}.object-meta.xml\n
"},{"location":"salesforce-deployment-assistant-error-list/#picklist-sharing-is-not-supported","title":"Picklist sharing is not supported","text":"

Detection

  • String: Picklist sharing is not supported

Resolution

You probably changed the type of a field.\nGo manually make the change in the target org, so the deployment will pass\n
"},{"location":"salesforce-deployment-assistant-error-list/#picklist-value-not-found","title":"Picklist value not found","text":"

Detection

  • RegExp: Picklist value: (.*) in picklist: (.*) not found

Resolution

Sources have references to value {1} of picklist {2}\n- If picklist {2} is standard, add the picklist to sfdx sources by using \"sf project retrieve start -m StandardValueSet:{2}\", then save again\n- Else, perform a search in all code of {1}, then remove XML tags referring to {1} (for example in record types metadatas)\n
"},{"location":"salesforce-deployment-assistant-error-list/#please-choose-a-different-name","title":"Please choose a different name","text":"

Detection

  • RegExp: Error (.*) This (.*) already exists or has been previously used(.*)Please choose a different name.

Resolution

- Rename {1} in the target org, then try again the deployment. if it succeeds, delete the renamed item.\n- or Delete {1} in the target org, then try again the deployment\n
"},{"location":"salesforce-deployment-assistant-error-list/#missing-profile-default-application","title":"Missing profile default application","text":"

Detection

  • String: You can't remove the only default app from the profile.

Resolution

You must have a default application for a profile. You can:\n - Update it in UI\n - Update the XML of the profile to set \"true\" in the <default> tag of one of the applicationVisibilities item.\n Ex:\n <applicationVisibilities>\n    <application>standard__LightningSales</application>\n    <default>true</default>\n    <visible>true</visible>\n</applicationVisibilities>\n
"},{"location":"salesforce-deployment-assistant-error-list/#crm-analytics-a-recipe-must-specify-a-dataflow","title":"CRM Analytics: A Recipe must specify a DataFlow","text":"

Detection

  • RegExp: Error (.*) A Recipe must specify a Dataflow

Resolution

You must include related WaveDataFlow {1} in sources (and probably in package.xml too).\nTo retrieve it, run: sf project retrieve start -m WaveDataFlow:{1} -u SOURCE_ORG_USERNAME\nYou can also retrieve all analytics sources in one shot using sf hardis:org:retrieve:source:analytics -u SOURCE_ORG_USERNAME\n  - https://salesforce.stackexchange.com/a/365453/33522\n  - https://help.salesforce.com/s/articleView?id=000319274&type=1\n
"},{"location":"salesforce-deployment-assistant-error-list/#record-type-not-found","title":"Record Type not found","text":"

Detection

  • RegExp: Error (.*) In field: recordType - no RecordType named (.*) found

Resolution

An unknown record type {2} is referenced in {1}\n- If record type {2} is not supposed to exist, perform a search in all files of {1}, then remove matching XML elements referring to this record type\n- If record type {2} is supposed to exist, you may have to create it manually in the target org to make the deployment pass\n
"},{"location":"salesforce-deployment-assistant-error-list/#objects-rights-on-a-role-is-below-org-default","title":"Objects rights on a role is below org default","text":"

Detection

  • String: access level below organization default

Resolution

Your org wide settings default must be lower than the level defined in roles:\n- If you are in a scratch org, it can be fixable using \"objectProperties\" in project-scratch-def.json (see \"Set Object-Level Sharing Settings\" paragraph in page https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_scratch_orgs_def_file.htm)\n- If you are in a sandbox/dev/prod org, you need to update default org wide settings before deployment. See https://www.sfdcpoint.com/salesforce/organization-wide-defaults-owd-in-salesforce/\n
"},{"location":"salesforce-deployment-assistant-error-list/#unsupported-sharing-configuration","title":"Unsupported sharing configuration","text":"

Detection

  • RegExp: not supported for (.*) since it's org wide default is

Resolution

Consistency error between {1} sharing settings and {1} object configuration\nPlease check https://salesforce.stackexchange.com/questions/260923/sfdx-deploying-contact-sharing-rules-on-a-fresh-deployment\nIf you already did that, please try again to run the job\n
"},{"location":"salesforce-deployment-assistant-error-list/#a-sharing-rule-may-be-useless","title":"A sharing rule may be useless","text":"

Detection

  • String: Required field is missing: sharingCriteriaRules

Resolution

Are you sure you need this sharing rule ? You may remove it from the sfdx project\n
"},{"location":"salesforce-deployment-assistant-error-list/#sharing-recalculation-lock","title":"Sharing recalculation lock","text":"

Detection

  • String: because it interferes with another operation already in progress
  • String: Le calcul de partage demand\u00e9 ne peut \u00eatre trait\u00e9 maintenant car il interf\u00e8re avec une autre op\u00e9ration en cours

Resolution

If you changed a field from MasterDetail to Lookup, you must do it manually in the target org before being able to deploy\n
"},{"location":"salesforce-deployment-assistant-error-list/#send-email-is-disabled","title":"Send email is disabled","text":"

Detection

  • String: Send Email is disabled or activities are not allowed
  • String: Unknown user permission: SendExternalEmailAvailable

Resolution

Go to Email -> Deliverability -> Select value \"All emails\"\n
"},{"location":"salesforce-deployment-assistant-error-list/#sort-order-must-be-in-sequential-order","title":"Sort order must be in sequential order","text":"

Detection

  • RegExp: Error (.*) SortOrder must be in sequential order from

Resolution

You probably have a default DuplicateRule in the target org. Retrieve it from target org, or delete it manually in target org, so you can deploy.\nRef: https://developer.salesforce.com/forums/?id=9060G000000I6SoQAK\n
"},{"location":"salesforce-deployment-assistant-error-list/#async-exception-in-test-class","title":"Async exception in test class","text":"

Detection

  • RegExp: System.AsyncException: (.*) Apex

Resolution

This may be a test class implementation issue in {1}.\nPlease check https://developer.salesforce.com/forums/?id=9060G0000005kVLQAY\n
"},{"location":"salesforce-deployment-assistant-error-list/#test-classes-with-0-coverage","title":"Test classes with 0% coverage","text":"

Detection

  • RegExp: 0%

Resolution

Please make sure that none of the test classes are 0% covered\n
"},{"location":"salesforce-deployment-assistant-error-list/#can-not-test-item-deployment-in-simulation-mode","title":"Can not test item deployment in simulation mode","text":"

Detection

  • RegExp: Test only deployment cannot update

Resolution

THIS IS A FALSE POSITIVE\nWhen effective deployment will happen, it should pass\n
"},{"location":"salesforce-deployment-assistant-error-list/#unknown-user-permission-createauditfields","title":"Unknown user permission: CreateAuditFields","text":"

Detection

  • String: Unknown user permission: CreateAuditFields

Resolution

You need to enable the \"Create audit field\" permission in the target org\nPlease check https://help.salesforce.com/articleView?id=000334139&type=1&mode=1\n
"},{"location":"salesforce-deployment-assistant-error-list/#unknown-user-permission-fieldserviceaccess","title":"Unknown user permission: FieldServiceAccess","text":"

Detection

  • String: Unknown user permission: FieldServiceAccess

Resolution

You need to enable the \"Field Service Access\" permission in the target org\nPlease check https://help.salesforce.com/articleView?id=sf.fs_enable.htm&type=5\n
"},{"location":"salesforce-deployment-assistant-error-list/#unknown-user-permission","title":"Unknown user permission","text":"

Detection

  • String: Unknown user permission:

Resolution

You can:\n- enable the related permission in the target org\n- or remove references to the permission in source XML files (Probably a Profile or a Permission set)\n
"},{"location":"salesforce-deployment-assistant-error-list/#variable-does-not-exist","title":"Variable does not exist","text":"

Detection

  • RegExp: Error (.*) Variable does not exist: (.*) \\((.*)\\)

Resolution

Apex error in {1} with unknown variable {2} at position {3}. If {2} is a class name, try to fix it, or maybe it is missing in the files or in package.xml !\n
"},{"location":"salesforce-deployment-assistant-error-list/#visibility-is-not-allowed-for-type","title":"Visibility is not allowed for type","text":"

Detection

  • RegExp: Error (.*) set the visibility for a (.*) to Protected unless you are in a developer

Resolution

Update the visibility of {1} to \"Public\"\n
"},{"location":"salesforce-deployment-assistant-error-list/#tableau-crm-wave-digest-error","title":"Tableau CRM / Wave digest error","text":"

Detection

  • String: Fix the sfdcDigest node errors and then upload the file again

Resolution

Go to the target org, open profile \"Analytics Cloud Integration User\" and add READ rights to the missing object fields \n
"},{"location":"salesforce-deployment-assistant-error-list/#xml-item-appears-more-than-once","title":"XML item appears more than once","text":"

Detection

  • RegExp: Error (.*) Field:(.*), value:(.*) appears more than once

Resolution

You probably made an error while merging conflicts\nLook for {3} in the XML of {1}\nIf you see two {2} XML blocks with {3}, please decide which one you keep and remove the other one\n
"},{"location":"salesforce-deployment-assistant-home/","title":"Sfdx-hardis deployment assistant","text":""},{"location":"salesforce-deployment-assistant-home/#sfdx-hardis-deployment-assistant","title":"sfdx-hardis Deployment Assistant","text":""},{"location":"salesforce-deployment-assistant-home/#salesforce-devops-ai-integration","title":"Salesforce DevOps AI Integration","text":"

Deployment errors are common and quite boring, right ?

Sfdx-hardis deployment assistant will help you to solve them, even if you are not using sfdx-hardis CI/CD pipelines !

The assistant contain core rules and can optionally be integrated with AI to provide you the best guidance :)

"},{"location":"salesforce-deployment-assistant-home/#flow-visual-git-diff","title":"Flow Visual Git Diff","text":"

In addition to deployment tips, comments will be posted on PRs with Visual Git Diff for Flows, that will:

  • Visually show you the differences on a diagram
  • Display the update details without having to open any XML !

\ud83d\udfe9 = added

\ud83d\udfe5 = removed

\ud83d\udfe7 = updated

"},{"location":"salesforce-deployment-assistant-home/#integrations","title":"Integrations","text":"

Deployment assistant will provide tips in Pull Request comments (GitHub, Gitlab, Azure, Bitbucket).

It will also provide tips in console log.

"},{"location":"salesforce-deployment-assistant-home/#setup","title":"Setup","text":"

Just follow the instructions to be ready in a few minutes

  • sfdx-hardis deployment assistant setup instructions
  • sfdx-hardis AI setup instructions (requires an Openai API key)
"},{"location":"salesforce-deployment-assistant-setup/","title":"Sfdx-hardis deployment assistant setup","text":""},{"location":"salesforce-deployment-assistant-setup/#setup-salesforce-deployment-assistant","title":"Setup Salesforce Deployment Assistant","text":""},{"location":"salesforce-deployment-assistant-setup/#configure-integrations","title":"Configure integrations","text":"

Make sure to have configured your GitHub, Gitlab, Azure Pipelines or BitBucket integration so the deployment assistant can post its help in Pull Request comments.

If you want to supercharge Salesforce deployment assistant with AI, process sfdx-hardis AI setup.

You can also receive Slack, Ms Teams and Email notifications in case of successful deployment.

If you configure JIRA or Generic Ticketing integrations, ticket numbers will be extracted and displayed in the Pull Request comment.

"},{"location":"salesforce-deployment-assistant-setup/#using-sfdx-hardis-cicd","title":"Using sfdx-hardis CI/CD","text":"

If you are using sfdx-hardis CI/CD, you are already all set !

"},{"location":"salesforce-deployment-assistant-setup/#using-custom-cicd-pipeline","title":"Using custom CI/CD pipeline","text":"

Replace your calls to Salesforce CLI by calls to sfdx-hardis commands wrapper.

sfdx command Corresponding sfdx-hardis wrapper command sf project deploy start sf hardis:project:deploy:start sf project deploy validate sf hardis:project:deploy:validate sf project deploy quick sf hardis:project:deploy:quick sfdx force:source:deploy (removed on 6 november) sf hardis:source:deploy sfdx force:source:push (removed on 6 november) sf hardis:source:push sfdx force:mdapi:deploy (removed on 6 november) sf hardis:mdapi:deploy

Configure your GitHub, Gitlab, Azure Pipelines or BitBucket integration so the deployment assistant can post its help in Pull Request comments.

Notes:

  • sfdx-hardis deployment assistant now works better with --json option please use it :)
"},{"location":"salesforce-deployment-assistant-setup/#example","title":"Example","text":"

Replace:

sf project:deploy:start -x manifest/package.xml --checkonly

with:

sf hardis:project:deploy:start -x manifest/package.xml --checkonly

"},{"location":"salesforce-deployment-assistant-setup/#advanced-example","title":"Advanced example","text":"

Replace:

sf project deploy start --dry-run --source-dir force-app --ignore-warnings --ignore-conflicts --test-level RunLocalTests --coverage-formatters json-summary --verbose --wait 120 --json

with:

sf hardis project deploy start --dry-run --source-dir force-app --ignore-warnings --ignore-conflicts --test-level RunLocalTests --coverage-formatters json-summary --verbose --wait 120 --json

"},{"location":"salesforce-deployment-assistant-setup/#not-updating-custom-cicd-pipeline","title":"Not updating custom CI/CD pipeline","text":"

You don't want to update your calls to sf project deploy start ?

That's ok, you can't benefit from the error management, but you can benefit from the Flows Visual Git Diff and other integrations anyway !

Add the Notify command to your custom CI/CD pipeline !

"},{"location":"salesforce-monitoring-apex-tests/","title":"Apex tests (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-apex-tests/#apex-tests","title":"Apex tests","text":"

Runs all local test classes of the org and calculate coverage.

Sfdx-hardis command: sf hardis:org:test:apex

"},{"location":"salesforce-monitoring-apex-tests/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-apex-tests/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-config-azure/","title":"Configure Salesforce Org Monitoring with Azure","text":"
  • Pre-requisites
    • Create access token
    • Create CI/CD variable
  • Run sfdx-hardis configuration command
  • Define sfdx-hardis environment variables
  • Schedule the monitoring job
"},{"location":"salesforce-monitoring-config-azure/#pre-requisites","title":"Pre-requisites","text":""},{"location":"salesforce-monitoring-config-azure/#configure-a-bypass-in-azure-settings","title":"Configure a ByPass in Azure Settings","text":"
  • Go to Project Settings \u2013> Repositories \u2013> select your repository and then click on the Security tab.
  • Select your Build Service and set Bypass policies when pushing and Contribute to Allowed
"},{"location":"salesforce-monitoring-config-azure/#run-sfdx-hardis-configuration-command","title":"Run sfdx-hardis configuration command","text":"
  • Run command Configuration -> Configure Org Monitoring in VsCode SFDX Hardis, then follow instructions.
  • When prompted to setup CI/CD variables, copy-paste their names and values in a notepad the continue the instructions
"},{"location":"salesforce-monitoring-config-azure/#create-pipeline","title":"Create Pipeline","text":"

Skip this step if you already created the pipeline for the monitoring of another org

  • Go to Project -> Pipelines (you must have Azure authorizations to access this menu)
  • Click on New pipeline
  • Where is your code -> Azure Repos Git
  • Select your monitoring git repository: Existing Azure Pipelines YAML file
  • Select your git branch then select azure-pipelines.yml
  • Click on Continue
  • Click on Save (contextual to the Run button)

"},{"location":"salesforce-monitoring-config-azure/#configure-cicd-variables","title":"Configure CI/CD Variables","text":"

For each variable sfdx-hardis command Configure org monitoring told you to define, perform the following operations

"},{"location":"salesforce-monitoring-config-azure/#create-variable-in-azure","title":"Create variable in Azure","text":"
  • Go to Project -> Pipelines
  • Select your pipeline
  • Click on Edit , then on Variables
  • Input variable name and value
  • Don't forget to click on save !
"},{"location":"salesforce-monitoring-config-azure/#update-azure-pipelinesyml","title":"Update azure-pipelines.yml","text":"
  • Open azure-pipelines.yml in VsCode and update all places where MANUAL is found
    • schedule triggers
    • environment variables

Examples:

schedules:\n- cron: \"0 4 * * *\" # Cron format -> https://crontab.cronhub.io/\n  always: \"true\"\n  branches:\n    # MANUAL: Add your monitored branches here\n    include:\n    - monitoring_myclient__integ_sandbox # Name of your branch created by monitoring configuration command\n
    env:\n      # MANUAL: Add your branch related variables here\n      SFDX_CLIENT_ID_MONITORING_MYCLIENT__INTEG_SANDBOX: $(SFDX_CLIENT_ID_MONITORING_MYCLIENT__INTEG_SANDBOX)\n      SFDX_CLIENT_KEY_MONITORING_MYCLIENT__INTEG_SANDBOX: $(SFDX_CLIENT_KEY_MONITORING_MYCLIENT__INTEG_SANDBOX)\n      CI_COMMIT_REF_NAME: $(BRANCH_NAME)\n      CONFIG_BRANCH: $(BRANCH_NAME)\n      ORG_ALIAS: $(BRANCH_NAME)\n      CI: \"true\"\n
  • Commit and push
"},{"location":"salesforce-monitoring-config-azure/#schedule-the-monitoring-job","title":"Schedule the monitoring job","text":"

Schedule is already included within azure-pipelines.yml.

Default is everyday at 4 AM, but you can update the CRON expression.

schedules:\n- cron: \"0 4 * * *\" # Cron format -> https://crontab.cronhub.io/\n

When updated, commit and push.

"},{"location":"salesforce-monitoring-config-bitbucket/","title":"Configure Salesforce Org Monitoring with Bitbucket","text":""},{"location":"salesforce-monitoring-config-bitbucket/#cloning-repo-from-vscode","title":"Cloning repo from VsCode","text":"

If you have issues to authenticate to Bitbucket from VsCode, create an App Password in Bitbucket personal settings.

"},{"location":"salesforce-monitoring-config-bitbucket/#pre-requisites","title":"Pre-requisites","text":"

There are no pre-requisites

"},{"location":"salesforce-monitoring-config-bitbucket/#run-sfdx-hardis-configuration-command","title":"Run sfdx-hardis configuration command","text":"
  • Run command Configuration -> Configure Org Monitoring in VsCode SFDX Hardis, then follow instructions.
"},{"location":"salesforce-monitoring-config-bitbucket/#define-sfdx-hardis-environment-variables","title":"Define sfdx-hardis environment variables","text":"
  • Go to Project -> Repository Settings > Repository Variables (you must have Bitbucket authorizations to access this menu)
  • For each variable sfdx-hardis command Configure org monitoring tells you to define, create with name and value given in sfdx-hardis command logs
"},{"location":"salesforce-monitoring-config-bitbucket/#schedule-the-monitoring-job","title":"Schedule the monitoring job","text":"
  • Go to Project -> Pipelines -> Schedules
  • Click on New schedule
  • Select the target branch corresponding to the org you want to monitor
  • Select default pipeline
  • Select Schedule Daily and a time slot when no one works (for example 01:00 - 02:00)
  • Validate by clicking on Create
"},{"location":"salesforce-monitoring-config-github/","title":"Configure Salesforce Org Monitoring with Github","text":"
  • Pre-requisites
  • Run sfdx-hardis configuration command
  • Define sfdx-hardis environment variables
  • Schedule the monitoring job
"},{"location":"salesforce-monitoring-config-github/#pre-requisites","title":"Pre-requisites","text":"

None

"},{"location":"salesforce-monitoring-config-github/#run-sfdx-hardis-configuration-command","title":"Run sfdx-hardis configuration command","text":"
  • Run command Configuration -> Configure Org Monitoring in VsCode SFDX Hardis, then follow instructions.
"},{"location":"salesforce-monitoring-config-github/#define-sfdx-hardis-environment-variables","title":"Define sfdx-hardis environment variables","text":"
  • Go to Repository -> Settings > Secret and variables -> Actions (you must have Github authorizations to access this menu)
  • For each variable sfdx-hardis command Configure org monitoring tells you to define, click on New repository secret, with name and value given in sfdx-hardis command logs
"},{"location":"salesforce-monitoring-config-github/#update-org-monitoringyml","title":"Update org-monitoring.yml","text":"

WARNING: Scheduling can be run only on main branch on GitHub Actions, so there is a specific config.

  • Configure all your monitored org using VsCode SFDX Hardis command \"Configure Org Monitoring\" (jobs will fail but that's ok)
    • Reply questions, configure variables, let sfdx-hardis upload connected apps...
    • This will create one git branch per monitored org

AND ONLY THEN:

  • Checkout your \"main\" branch, create a file .github/workflows/org-monitoring.yml and copy there the content of org-monitoring.yml
    • Do a CTRL+F and look for MANUAL
    • Add your monitored git branches here where asked to replace
    • Add your authentication variable names where asked to replace
    • Commit & push: there should be a SINGLE GitHub Actions job (using matrix) that will run the monitoring on all orgs

Examples:

      env:\n        # MANUAL: Update variables below !\n        SFDX_CLIENT_ID_MONITORING_MY_CLIENT__INTEG_SANDBOX: ${{ secrets.SFDX_CLIENT_ID_MONITORING_MY_CLIENT__INTEG_SANDBOX}}\n        SFDX_CLIENT_KEY_MONITORING_MY_CLIENT__INTEG_SANDBOX: ${{ secrets.SFDX_CLIENT_KEY_MONITORING_MY_CLIENT__INTEG_SANDBOX}}\n        SFDX_DEPLOY_WAIT_MINUTES: 120 # Override if necessary\n
"},{"location":"salesforce-monitoring-config-github/#schedule-the-monitoring-job","title":"Schedule the monitoring job","text":"

Schedule is already included within org-monitoring.yml in main branch.

Default is everyday at midnight, but you can update the CRON expression.

on:\n  push:\n  # Automatically run every day at midnight\n  schedule:\n    - cron: \"0 0 * * *\" # Cron format -> https://crontab.cronhub.io/\n
"},{"location":"salesforce-monitoring-config-gitlab/","title":"Configure Salesforce Org Monitoring with Gitlab","text":"
  • Pre-requisites
    • Create access token
    • Create CI/CD variable
  • Run sfdx-hardis configuration command
  • Define sfdx-hardis environment variables
  • Schedule the monitoring job
"},{"location":"salesforce-monitoring-config-gitlab/#pre-requisites","title":"Pre-requisites","text":""},{"location":"salesforce-monitoring-config-gitlab/#create-access-token","title":"Create access token","text":"
  • Go to Project -> Settings > Access Token (you must have Gitlab authorizations to access this menu)
  • Create an access token with the following info:
    • name: SFDX HARDIS MONITORING
    • role: Developer
    • scopes: read_repository, write_repository
  • Copy the value of the generated token in your clipboard ! (CTRL+C)
"},{"location":"salesforce-monitoring-config-gitlab/#create-cicd-variable","title":"Create CI/CD variable","text":"
  • Go to Project -> Settings > CI/CD -> Variables (you must have Gitlab authorizations to access this menu)
  • Create the variable with the following info:
    • name: ACCESS_TOKEN
    • value: Paste the value that has been generated when creating the access token in the previous step
    • Select Mask variable
    • Unselect Protected variable
"},{"location":"salesforce-monitoring-config-gitlab/#run-sfdx-hardis-configuration-command","title":"Run sfdx-hardis configuration command","text":"
  • Run command Configuration -> Configure Org Monitoring in VsCode SFDX Hardis, then follow instructions.
"},{"location":"salesforce-monitoring-config-gitlab/#define-sfdx-hardis-environment-variables","title":"Define sfdx-hardis environment variables","text":"
  • Go to Project -> Settings > CI/CD -> Variables (you must have Gitlab authorizations to access this menu)
  • For each variable sfdx-hardis command Configure org monitoring tells you to define, create with name and value given in sfdx-hardis command logs
"},{"location":"salesforce-monitoring-config-gitlab/#schedule-the-monitoring-job","title":"Schedule the monitoring job","text":"
  • Go to Project -> Build -> Pipeline schedules
  • Click on New schedule
  • Input custom interval pattern as CRON expression, for example:
    • 0 1 * * * will run the monitoring job every day at 1 AM
    • 0 22 * * * will run the monitoring job everyday at 10 PM
  • Select the CRON TimeZone (for example [UTC+2] Paris)
  • Select the target branch corresponding to the org you want to monitor
  • Validate by clicking on Create Pipeline Schedule
"},{"location":"salesforce-monitoring-config-home/","title":"How to monitor your Salesforce Org","text":"
  • Video tutorial
  • Instructions
    • Common instructions
    • Github
    • Gitlab
    • Azure
    • Bitbucket
  • Notifications
  • Troubleshooting
"},{"location":"salesforce-monitoring-config-home/#video-tutorial","title":"Video tutorial","text":""},{"location":"salesforce-monitoring-config-home/#instructions","title":"Instructions","text":""},{"location":"salesforce-monitoring-config-home/#common-instructions","title":"Common instructions","text":"

All you need to configure sfdx-hardis Org Monitoring is a GitHub , Gitlab, Azure or BitBucket repository.

  • Create and clone a git repository (initialize it with README)
  • Open it with Visual Studio Code, then open VsCode SFDX Hardis extension menu.
    • If you need installations instructions, please visit documentation page
  • Follow instructions, that can be specific according to your git provider

Tip: Schedule monitoring jobs at different hours so the notifications are more readable, for example production at 1AM and preprod at 2AM

"},{"location":"salesforce-monitoring-config-home/#github","title":"Github","text":"
  • GitHub configuration
    • Pre-requisites
    • Schedule monitoring job
"},{"location":"salesforce-monitoring-config-home/#gitlab","title":"Gitlab","text":"
  • Gitlab configuration
    • Pre-requisites
    • Schedule monitoring job
"},{"location":"salesforce-monitoring-config-home/#azure","title":"Azure","text":"
  • Azure configuration
    • Pre-requisites
    • Schedule monitoring job
"},{"location":"salesforce-monitoring-config-home/#bitbucket","title":"Bitbucket","text":"
  • Bitbucket configuration
    • Pre-requisites
    • Schedule monitoring job
"},{"location":"salesforce-monitoring-config-home/#notifications","title":"Notifications","text":"

For a better user experience, it is highly recommended to configure notifications !

  • Slack instructions
  • Microsoft Teams instructions
  • Email instructions
  • Grafana instructions (example: for Grafana Loki integration)

You can decide to run commands but not send some notifications by defining either a notificationsDisable property in .sfdx-hardis.yml, or a comma separated list in env variable NOTIFICATIONS_DISABLE

Example in .sfdx-hardis.yml:

notificationsDisable:\n  - METADATA_STATUS\n  - UNUSED_METADATAS\n

Example in env var:

NOTIFICATIONS_DISABLE=METADATA_STATUS,UNUSED_METADATAS\n
"},{"location":"salesforce-monitoring-config-home/#monitoring-commands","title":"Monitoring commands","text":"

You can decide to disable commands by defining either a monitoringDisable property in .sfdx-hardis.yml, or a comma separated list in env variable MONITORING_DISABLE

Example in .sfdx-hardis.yml:

monitoringDisable:\n  - METADATA_STATUS\n  - UNUSED_METADATAS\n

Example in env var:

MONITORING_DISABLE=METADATA_STATUS,UNUSED_METADATAS\n
"},{"location":"salesforce-monitoring-config-home/#troubleshooting","title":"Troubleshooting","text":"

You might want to customize which metadatas types are backuped, because you can't monitor more than 10000 items.

If there are more than 10000 items, your monitoring job will crash.

In that case, you can:

  • Single Branch scope: Manually update file manifest/package-skip-items.xml in the branch corresponding to an org, then commit and push
  • All branches scope: Define CI/CD env var MONITORING_BACKUP_SKIP_METADATA_TYPES with the list of additional metadata types you want to skip
    • example: `MONITORING_BACKUP_SKIP_METADATA_TYPES=CustomLabel,StaticResource,Translation`
"},{"location":"salesforce-monitoring-deprecated-api-calls/","title":"Suspect Setup Actions (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-deprecated-api-calls/#detect-calls-to-deprecated-api-versions","title":"Detect calls to deprecated API versions","text":"

Will check if legacy API versions are called by external tools.

Sfdx-hardis command: sf hardis:org:diagnose:legacyapi

Key: LEGACY_API

"},{"location":"salesforce-monitoring-deprecated-api-calls/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-deprecated-api-calls/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-home/","title":"How to monitor your Salesforce Org","text":"
  • Monitor your Salesforce org with sfdx-hardis
  • How does it work ?
  • All Monitoring Commands
"},{"location":"salesforce-monitoring-home/#monitor-your-salesforce-org-with-sfdx-hardis","title":"Monitor your Salesforce org with sfdx-hardis","text":"

This feature worked yesterday in production, but today it crashes, what happened ?

Instead of reading, watch the presentation at Dreamforce 24 conference in San Francisco !

or if you like reading, here are the slides !

Salesforce provide Audit Trail to trace configuration updates in production or sandbox orgs.

You can know who updated what, but not with details (before / after).

Sfdx-hardis monitoring provides a simple way to Backup your orgs metadatas everyday, or even several times a day, and provides an exact and detailed comparison with the previous metadata configuration (using git commits comparison)

Extra indicators are also available out of the box, like:

  • Run apex tests (and soon flow tests)
  • Analyze the quality and the security of your metadatas with MegaLinter
  • Checking org limits
  • Be warned of release updates
  • Check if you have deprecated api versions called
  • Custom command lines that you can define in .sfdx-hardis.yml

You don't need to work in CI/CD to use Monitoring, it is compliant with any API enabled org :)

Installation and usage are admin-friendly, and notifications can be sent via Slack or Microsoft Teams.

Example of visualization in Grafana

Example notifications with Slack

Example of a monitoring git repository

"},{"location":"salesforce-monitoring-home/#how-does-it-work","title":"How does it work ?","text":"

Every night (or even more frequently, according to your schedule), a CI job will be triggered.

It will extract all the metadatas of your org, then push a new commit in the monitoring repository in case there are updates since the latest metadata backup.

Example workflow with GitHub actions

Example diff visualization with GitLens

The list of updated metadatas will be sent via notification to a Slack and/or Microsoft Teams channel.

After the metadata backup, other jobs will be triggered (Apex tests, Code Quality, Legacy API checks + your own commands), and their results will be stored in job artifacts and sent via notifications.

Are you ready ? Configure the monitoring on your orgs !

"},{"location":"salesforce-monitoring-home/#all-monitoring-commands","title":"All Monitoring Commands","text":"

The following checks are active out of the box.

In order to avoid to overflow channels of notifications, some commands are run everyday whereas less critical ones are run weekly (on saturday).

You can force the daily run of all commands by defining env var MONITORING_IGNORE_FREQUENCY=true.

Check Frequency Metadata Backup Daily Detect suspect setup actions in major org Daily Apex tests Daily Quality Checks with MegaLinter Daily Detect limits issues Daily Detect calls to deprecated API versions Daily Check Release Updates Weekly Detect inactive users Weekly Detect not used Apex Classes (Batch,Schedulable,Queueable) Weekly Detect not used Connected Apps Weekly Detect unused licenses Weekly Detect custom elements with no access rights defined in permission sets Weekly Detect custom labels and custom permissions that are not in use Weekly Detect inactive metadata Weekly Detect missing attributes Weekly"},{"location":"salesforce-monitoring-inactive-metadata/","title":"Inactive Metadatas (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-inactive-metadata/#detect-inactive-metadata","title":"Detect inactive metadata","text":"

Are you sure this inactive flow should be inactive ?

And what about this deactivated Validation Rule ?

Maybe it's time to remove them !

Sfdx-hardis command: sf hardis:lint:metadatastatus

Key: METADATA_STATUS

"},{"location":"salesforce-monitoring-inactive-metadata/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-inactive-metadata/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-inactive-users/","title":"Inactive Users (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-inactive-users/#detect-inactive-users","title":"Detect inactive users","text":"

Detect if you are paying licenses for users that did not login for more than 6 months !

Sfdx-hardis command: sf hardis:org:diagnose:unusedusers

Key: UNUSED_USERS

"},{"location":"salesforce-monitoring-inactive-users/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-inactive-users/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-metadata-backup/","title":"Metadata backup (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-metadata-backup/#metadata-backup","title":"Metadata Backup","text":"

Adds a new commit in the git branch with the newest updates since latest monitoring run.

Sfdx-hardis command: sf hardis:org:monitor:backup

"},{"location":"salesforce-monitoring-metadata-backup/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-metadata-backup/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-missing-access/","title":"Missing metadata access (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-missing-access/#detect-custom-elements-with-no-access-rights-defined-in-permission-sets","title":"Detect custom elements with no access rights defined in permission sets","text":"

If there are elements that nobody has access to (not existing on any Profile or Permission Set), maybe they should be removed !

Sfdx-hardis command: sf hardis:lint:access

Key: LINT_ACCESS

"},{"location":"salesforce-monitoring-missing-access/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-missing-access/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-missing-metadata-attributes/","title":"Missing metadata attributes (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-missing-metadata-attributes/#detect-missing-attributes","title":"Detect missing attributes","text":"

Follow best practices by documenting your data model !

Sfdx-hardis command: sf hardis:lint:missingattributes

Key: MISSING_ATTRIBUTES

"},{"location":"salesforce-monitoring-missing-metadata-attributes/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-missing-metadata-attributes/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-org-limits/","title":"Org limits (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-org-limits/#detect-org-limits-issues","title":"Detect org limits issues","text":"

There are many limits on a Salesforce org:

  • Data storage
  • File storage
  • Daily API Calls
  • Daily Bulk API Calls
  • Daily Platform events
  • and about 40 others !

This feature controls that they are not reached, and will send notifications:

  • Info: > 50%
  • Warning > 75%
  • Error > 100%

Sfdx-hardis command: sf hardis:org:monitor:limits

Key: ORG_LIMITS

"},{"location":"salesforce-monitoring-org-limits/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-org-limits/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-quality-checks/","title":"Quality Checks with MegaLinter (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-quality-checks/#quality-checks-with-megalinter","title":"Quality Checks with MegaLinter","text":"

Will check if best practices are applied for:

  • Apex with PMD
  • LWC & Aura with eslint
  • Flows with Lightning Flow Scanner
  • Security with checkov, gitleaks, secretlint, trivy...

Full list in MegaLinter Documentation

"},{"location":"salesforce-monitoring-release-updates/","title":"Check Release Updates (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-release-updates/#check-release-updates","title":"Check Release Updates","text":"

Before publishing Breaking Changes \u274c, Salesforce announce them in the setup menu Release Updates

\u26a0\ufe0f Some of them are very important, because if you don't make the related upgrades in time (ex: before Winter 25) , your production org can crash !

This command will extract the Release Updates that needs to be checked in your org !

Sfdx-hardis command: sf hardis:org:diagnose:releaseupdates

Key: RELEASE_UPDATES*

"},{"location":"salesforce-monitoring-release-updates/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-release-updates/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-suspect-audit-trail/","title":"Suspect Setup Actions (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-suspect-audit-trail/#detect-suspect-setup-actions-in-major-org","title":"Detect suspect setup actions in major org","text":"

Will extract from audit trail all actions that are considered as suspect, excepted the ones related to the deployment user and a given list of users, like the release manager.

Sfdx-hardis command: sf hardis:org:diagnose:audittrail

Key: AUDIT_TRAIL

"},{"location":"salesforce-monitoring-suspect-audit-trail/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-suspect-audit-trail/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-unused-apex-classes/","title":"Detect unused Apex Classes (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-unused-apex-classes/#detect-unused-apex-classes","title":"Detect unused Apex Classes","text":"

List all async Apex classes (Batch,Queueable,Schedulable) that has not been called for more than 365 days.

The result class list probably can be removed from the project, and that will improve your test classes performances :)

The command uses queries on AsyncApexJob and CronTrigger technical tables to build the result.

Sfdx-hardis command: sf hardis:org:diagnose:unused-apex-classes

Key: UNUSED_APEX_CLASSES

"},{"location":"salesforce-monitoring-unused-apex-classes/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-unused-apex-classes/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-unused-connected-apps/","title":"Detect unused Connected Apps (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-unused-connected-apps/#detect-unused-connected-apps","title":"Detect unused Connected Apps","text":"

List all Connected Apps that might be not used anymore

You might disable them or even delete them to clean your org from technical debt and avoid security risks.

Sfdx-hardis command: sf hardis:org:diagnose:unused-connected-apps

Key: CONNECTED_APPS

"},{"location":"salesforce-monitoring-unused-connected-apps/#grafana-example","title":"Grafana example","text":"

TODO

"},{"location":"salesforce-monitoring-unused-connected-apps/#slack-example","title":"Slack example","text":"

TODO

"},{"location":"salesforce-monitoring-unused-licenses/","title":"Unused Licenses (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-unused-licenses/#detect-unused-licenses","title":"Detect unused licenses","text":"

When you assign a Permission Set to a user, and that this Permission Set is related to a Permission Set License, a Permission Set License Assignment is automatically created for the user.

But when you unassign this Permission Set from the user, the Permission Set License Assignment is not deleted.

This leads that you can be charged for Permission Set Licenses that are not used !

This command detects such useless Permission Set Licenses Assignments and suggests to delete them.

Many thanks to Vincent Finet for the inspiration during his great speaker session at French Touch Dreamin '23, and his kind agreement for reusing such inspiration in this command :)

Sfdx-hardis command: sf hardis:org:diagnose:unusedlicenses

Key: UNUSED_LICENSES

"},{"location":"salesforce-monitoring-unused-licenses/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-unused-licenses/#slack-example","title":"Slack example","text":""},{"location":"salesforce-monitoring-unused-metadata/","title":"Unused Metadatas (Salesforce monitoring)","text":""},{"location":"salesforce-monitoring-unused-metadata/#detect-metadatas-that-are-not-used","title":"Detect metadatas that are not used","text":"

If there are elements that are not used by anything, maybe they should be removed !

Today working with:

  • Custom Labels
  • Custom Permissions

Sfdx-hardis command: sf hardis:lint:unusedmetadatas

Key: UNUSED_METADATAS

"},{"location":"salesforce-monitoring-unused-metadata/#grafana-example","title":"Grafana example","text":""},{"location":"salesforce-monitoring-unused-metadata/#slack-example","title":"Slack example","text":""},{"location":"salesforce-project-documentation/","title":"Generate Salesforce Project Documentation","text":""},{"location":"salesforce-project-documentation/#salesforce-project-documentation","title":"Salesforce Project Documentation","text":"

With a single command, you can generate a Web Site documenting your Salesforce metadatas (like Flows)

"},{"location":"salesforce-project-documentation/#how-to-generate","title":"How To generate","text":"
  • Use the Git repository containing your SFDX project, or create it easily using sfdx-hardis Monitoring, or simply calling BackUp command
  • Call VsCode SFDX-Hardis command Documentation Generation > Generate Project Documentation (with history)
    • Corresponding command line: sf hardis:doc:project2markdown --with-history
"},{"location":"salesforce-project-documentation/#run-locally","title":"Run Locally","text":"
  • Run command Documentation Generation > Run local HTML Doc Pages (Note: you need Python on your computer)
    • Corresponding command lines: pip install mkdocs-material mdx_truly_sane_lists, then mkdocs serve
  • Open http://127.0.0.1:8000/ in your Web Browser
"},{"location":"salesforce-project-documentation/#host-on-salesforce-org","title":"Host on Salesforce org","text":"

You can also host the HTML documentation directly in your Salesforce org !

"},{"location":"salesforce-project-documentation/#manually","title":"Manually","text":"
  • Run command Documentation Generation -> Upload HTML Doc to Salesforce
    • Corresponding command line: sf hardis:doc:mkdocs-to-salesforce
  • Set generated Custom Tab as Default On on your Profile if necessary
  • Assign generated Permission Set to the users you want to access the SFDX Doc tab
  • Add the tab in a Lightning Application (optional)
"},{"location":"salesforce-project-documentation/#from-cicd","title":"From CI/CD","text":"

If using sfdx-hardis monitoring, just set the variable SFDX_HARDIS_DOC_DEPLOY_TO_ORG=true (or the .sfdx-hardis.yml variable docDeployToOrg: true)

If using custom pipelines, add sf hardis:doc:project2markdown --with-history then sf hardis:doc:mkdocs-to-salesforce in your workflow.

"},{"location":"sfdx-hardis-config-file/","title":".sfdx-hardis.yml config file","text":"

sfdx-hardis projects are like any other sfdx projects, but with an additional configuration stored in a .sfdx-hardis.yml config file

Many of these properties are automatically set by CI/CD setup and maintenance operations.

You can see the list of all configuration properties.

Here is an example of a .sfdx-hardis.yml config file:

projectName: MyClient\ndevHubAlias: DevHub_MyClient\ndevelopmentBranch: integration\nallowedOrgTypes:\n  - sandbox\navailableTargetBranches:\n  - develop\n  - preprod\nautoCleanTypes:\n  - destructivechanges\n  - datadotcom\n  - minimizeProfiles\n  - listViewsMine\nautoRemoveUserPermissions:\n  - EnableCommunityAppLauncher\n  - FieldServiceAccess\n  - OmnichannelInventorySync\n  - SendExternalEmailAvailable\n  - UseOmnichannelInventoryAPIs\n  - ViewDataLeakageEvents\n  - ViewMLModels\n  - ViewPlatformEvents\n  - WorkCalibrationUser\nautoRetrieveWhenPull:\n  - CustomApplication:MyClient\n  - CustomApplication:MyClientConnectApplication\n  - CustomApplication:MyOtherApplication\n  - CustomMetadata\ndevHubUsername: nicolas.vuillamy@ext.myclient.com\ninstallPackagesDuringCheckDeploy: true\ninstalledPackages:\n  - Id: 0A37Z000000AtDYSA0\n    SubscriberPackageId: 033i0000000LVMYAA4\n    SubscriberPackageName: Marketing Cloud\n    SubscriberPackageNamespace: et4ae5\n    SubscriberPackageVersionId: 04t6S000001UjutQAC\n    SubscriberPackageVersionName: Marketing Cloud\n    SubscriberPackageVersionNumber: 238.3.0.2\n    installOnScratchOrgs: true\n    installDuringDeployments: true\n  - Id: 0A35r0000009F9CCAU\n    SubscriberPackageId: 033b0000000Pf2AAAS\n    SubscriberPackageName: Declarative Lookup Rollup Summaries Tool\n    SubscriberPackageNamespace: dlrs\n    SubscriberPackageVersionId: 04t5p000001BmLvAAK\n    SubscriberPackageVersionName: Release\n    SubscriberPackageVersionNumber: 2.15.0.9\n    installOnScratchOrgs: true\n    installDuringDeployments: true\ninitPermissionSets:\n  - AdminDefault\n  - MarketingCloudConnectedApp\n  - ApiUserPS\nlistViewsToSetToMine:\n  - force-app/main/default/objects/Operation__c/listViews/MyCurrentOperations.listView-meta.xml\n  - force-app/main/default/objects/Operation__c/listViews/MyFinalizedOperations.listView-meta.xml\n
"},{"location":"sfdx-hardis-help/","title":"sfdx-hardis help","text":"

You have a question or need assistance ?

Feel free to contact us \ud83d\ude42 :)

"},{"location":"special-thanks/","title":"Special Thanks about sfdx-hardis","text":""},{"location":"special-thanks/#trailblazer-community","title":"Trailblazer community","text":"
  • Roman Hentschke, for building the BitBucket CI/CD integration
  • Leo Jokinen, for building the GitHub CI/CD integration
"},{"location":"special-thanks/#contributors","title":"Contributors","text":""},{"location":"special-thanks/#inspirations","title":"Inspirations","text":""},{"location":"hardis/auth/login/","title":"login","text":""},{"location":"hardis/auth/login/#hardisauthlogin","title":"hardis:auth:login","text":""},{"location":"hardis/auth/login/#description","title":"Description","text":"

Login to salesforce org

"},{"location":"hardis/auth/login/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) devhub-h boolean Also connect associated DevHub flags-dir option undefined instanceurl-r option URL of org instance json boolean Format output as json. scratchorg-s boolean Scratch org skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/auth/login/#examples","title":"Examples","text":"
$ sf hardis:auth:login\n
"},{"location":"hardis/cache/clear/","title":"clear","text":""},{"location":"hardis/cache/clear/#hardiscacheclear","title":"hardis:cache:clear","text":""},{"location":"hardis/cache/clear/#description","title":"Description","text":"

Clear cache generated by sfdx-hardis

"},{"location":"hardis/cache/clear/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/cache/clear/#examples","title":"Examples","text":"
$ sf hardis:cache:clear\n
"},{"location":"hardis/config/get/","title":"get","text":""},{"location":"hardis/config/get/#hardisconfigget","title":"hardis:config:get","text":""},{"location":"hardis/config/get/#description","title":"Description","text":"

Returns sfdx-hardis project config for a given level

"},{"location":"hardis/config/get/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. level-l option project,branch or user project projectbranchuser skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/config/get/#examples","title":"Examples","text":"
$ sf hardis:project:deploy:sources:metadata\n
"},{"location":"hardis/deploy/quick/","title":"quick","text":""},{"location":"hardis/deploy/quick/#hardisdeployquick","title":"hardis:deploy:quick","text":""},{"location":"hardis/deploy/quick/#description","title":"Description","text":"

sfdx-hardis wrapper for sf project deploy quick that displays tips to solve deployment errors.

Note: Use --json argument to have better results

See documentation of Salesforce command

"},{"location":"hardis/deploy/quick/#deployment-pre-or-post-commands","title":"Deployment pre or post commands","text":"

You can define command lines to run before or after a deployment, with parameters:

  • id: Unique Id for the command
  • label: Human readable label for the command
  • skipIfError: If defined to \"true\", the post-command won't be run if there is a deployment failure
  • context: Defines the context where the command will be run. Can be all (default), check-deployment-only or process-deployment-only
  • runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)

If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

Example:

commandsPreDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='deploy.github@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n\ncommandsPostDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to desired username\n    command: sf data update record --sobject User --where \"Username='admin-yser@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n  - id: someActionToRunJustOneTime\n    label: And to run only if deployment is success\n    command: sf sfdmu:run ...\n    skipIfError: true\n    context: process-deployment-only\n    runOnlyOnceByOrg: true\n
"},{"location":"hardis/deploy/quick/#parameters","title":"Parameters","text":"Name Type Description Default Required Options --job-id-i option job-id --use-most-recent-r boolean use-most-recent api-version-a option api-version async boolean async debug boolean debug flags-dir option undefined json boolean Format output as json. target-org-o option undefined tests option tests wait-w option wait 33"},{"location":"hardis/deploy/quick/#examples","title":"Examples","text":""},{"location":"hardis/deploy/start/","title":"start","text":""},{"location":"hardis/deploy/start/#hardisdeploystart","title":"hardis:deploy:start","text":""},{"location":"hardis/deploy/start/#description","title":"Description","text":"

sfdx-hardis wrapper for sf project deploy start that displays tips to solve deployment errors.

Note: Use --json argument to have better results

See documentation of Salesforce command

"},{"location":"hardis/deploy/start/#deployment-pre-or-post-commands","title":"Deployment pre or post commands","text":"

You can define command lines to run before or after a deployment, with parameters:

  • id: Unique Id for the command
  • label: Human readable label for the command
  • skipIfError: If defined to \"true\", the post-command won't be run if there is a deployment failure
  • context: Defines the context where the command will be run. Can be all (default), check-deployment-only or process-deployment-only
  • runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)

If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

Example:

commandsPreDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='deploy.github@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n\ncommandsPostDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to desired username\n    command: sf data update record --sobject User --where \"Username='admin-yser@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n  - id: someActionToRunJustOneTime\n    label: And to run only if deployment is success\n    command: sf sfdmu:run ...\n    skipIfError: true\n    context: process-deployment-only\n    runOnlyOnceByOrg: true\n
"},{"location":"hardis/deploy/start/#parameters","title":"Parameters","text":"Name Type Description Default Required Options api-version-a option api-version async boolean async coverage-formatters option coverage-formatters debug boolean debug dry-run boolean dry-run flags-dir option undefined ignore-conflicts-c boolean ignore-conflicts ignore-errors-r boolean ignore-errors ignore-warnings-g boolean ignore-warnings json boolean Format output as json. junit boolean junit manifest-x option manifest metadata-m option metadata metadata-dir option metadata-dir post-destructive-changes option post-destructive-changes pre-destructive-changes option pre-destructive-changes purge-on-delete boolean purge-on-delete results-dir option results-dir single-package boolean single-package source-dir-d option source-dir target-org-o option undefined test-level option test-level tests option tests wait-w option wait 33"},{"location":"hardis/deploy/start/#examples","title":"Examples","text":""},{"location":"hardis/deploy/validate/","title":"validate","text":""},{"location":"hardis/deploy/validate/#hardisdeployvalidate","title":"hardis:deploy:validate","text":""},{"location":"hardis/deploy/validate/#description","title":"Description","text":"

sfdx-hardis wrapper for sf project deploy validate that displays tips to solve deployment errors.

Note: Use --json argument to have better results

See documentation of Salesforce command

"},{"location":"hardis/deploy/validate/#deployment-pre-or-post-commands","title":"Deployment pre or post commands","text":"

You can define command lines to run before or after a deployment, with parameters:

  • id: Unique Id for the command
  • label: Human readable label for the command
  • skipIfError: If defined to \"true\", the post-command won't be run if there is a deployment failure
  • context: Defines the context where the command will be run. Can be all (default), check-deployment-only or process-deployment-only
  • runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)

If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

Example:

commandsPreDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='deploy.github@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n\ncommandsPostDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to desired username\n    command: sf data update record --sobject User --where \"Username='admin-yser@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n  - id: someActionToRunJustOneTime\n    label: And to run only if deployment is success\n    command: sf sfdmu:run ...\n    skipIfError: true\n    context: process-deployment-only\n    runOnlyOnceByOrg: true\n
"},{"location":"hardis/deploy/validate/#parameters","title":"Parameters","text":"Name Type Description Default Required Options api-version-a option api-version async boolean async coverage-formatters option coverage-formatters debug boolean debug dry-run boolean dry-run flags-dir option undefined ignore-conflicts-c boolean ignore-conflicts ignore-errors-r boolean ignore-errors ignore-warnings-g boolean ignore-warnings json boolean Format output as json. junit boolean junit manifest-x option manifest metadata-m option metadata metadata-dir option metadata-dir post-destructive-changes option post-destructive-changes pre-destructive-changes option pre-destructive-changes purge-on-delete boolean purge-on-delete results-dir option results-dir single-package boolean single-package source-dir-d option source-dir target-org-o option undefined test-level option test-level tests option tests wait-w option wait 33"},{"location":"hardis/deploy/validate/#examples","title":"Examples","text":""},{"location":"hardis/doc/flow2markdown/","title":"flow2markdown","text":""},{"location":"hardis/doc/flow2markdown/#hardisdocflow2markdown","title":"hardis:doc:flow2markdown","text":""},{"location":"hardis/doc/flow2markdown/#description","title":"Description","text":"

Generates a markdown documentation from a Flow file

"},{"location":"hardis/doc/flow2markdown/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined inputfile-x option Path to Flow metadata file. If not specified, the command will prompt the user json boolean Format output as json. outputfile-f option Force the path and name of output markdown file. Must end with .md skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration with-history boolean Generate a markdown file with the history diff of the Flow"},{"location":"hardis/doc/flow2markdown/#examples","title":"Examples","text":"
$ sf hardis:doc:flow2markdown\n
$ sf hardis:doc:flow2markdown --inputfile force-app/main/default/flows/MyFlow.flow-meta.xml\n
"},{"location":"hardis/doc/mkdocs-to-salesforce/","title":"mkdocs-to-salesforce","text":""},{"location":"hardis/doc/mkdocs-to-salesforce/#hardisdocmkdocs-to-salesforce","title":"hardis:doc:mkdocs-to-salesforce","text":""},{"location":"hardis/doc/mkdocs-to-salesforce/#description","title":"Description","text":"

Generates MkDocs HTML pages and upload them to Salesforce as a static resource

This command performs the following operations:

  • Generates MkDocs HTML pages (using locally installed mkdocs-material, or using mkdocs docker image)
  • Creates a Static Resource, a VisualForce page and a Custom Tab metadata
  • Upload the metadatas to the default org
  • Opens the Custom Tab in the default browser (only if not in CI context)

Note: the documentation must have been previously generated using \"sf hardis:doc:project2markdown --with-history\"

You can:

  • Specify the type of documentation to generate (CICD or Monitoring) using the --type flag. Default is CICD.
  • Override default styles by customizing mkdocs.yml

More info on Documentation section

"},{"location":"hardis/doc/mkdocs-to-salesforce/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined type-t option Type of the documentation to generate. Default is \"all\" CICD CICDMonitoring websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/doc/mkdocs-to-salesforce/#examples","title":"Examples","text":"
$ sf hardis:doc:mkdocs-to-salesforce\n
"},{"location":"hardis/doc/packagexml2markdown/","title":"packagexml2markdown","text":""},{"location":"hardis/doc/packagexml2markdown/#hardisdocpackagexml2markdown","title":"hardis:doc:packagexml2markdown","text":""},{"location":"hardis/doc/packagexml2markdown/#description","title":"Description","text":"

Generates a markdown documentation from a package.xml file

"},{"location":"hardis/doc/packagexml2markdown/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined inputfile-x option Path to package.xml file. If not specified, the command will look in manifest folder json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .md skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/doc/packagexml2markdown/#examples","title":"Examples","text":"
$ sf hardis:doc:packagexml2markdown\n
$ sf hardis:doc:packagexml2markdown --inputfile manifest/package-all.xml\n
"},{"location":"hardis/doc/project2markdown/","title":"project2markdown","text":""},{"location":"hardis/doc/project2markdown/#hardisdocproject2markdown","title":"hardis:doc:project2markdown","text":""},{"location":"hardis/doc/project2markdown/#description","title":"Description","text":"

Generates a markdown documentation from a SFDX project

  • Package.xml files
  • Source Packages
  • sfdx-hardis configuration
  • Installed packages

Can work on any sfdx project, no need for it to be a sfdx-hardis flavored one.

Generates markdown files will be written in docs folder (except README.md where a link to doc index is added)

To read Flow documentations if your markdown reader doesn't handle MermaidJS syntax, this command could require @mermaid-js/mermaid-cli

  • Run npm install @mermaid-js/mermaid-cli --global if puppeteer works in your environment
  • It can also be run as a docker image

Both modes will be tried by default, but you can also force one of them by defining environment variable MERMAID_MODES=docker or MERMAID_MODES=cli

sfdx-hardis docker image is alpine-based and does not succeed to run mermaid/puppeteer: if you can help, please submit a PR !

If Flow history doc always display a single state, you probably need to update your workflow configuration:

  • on Gitlab: Env variable GIT_FETCH_EXTRA_FLAGS: --depth 10000
  • on GitHub: fetch-depth: 0
  • on Azure: fetchDepth: \"0\"
  • on Bitbucket: step: clone: depth: full

"},{"location":"hardis/doc/project2markdown/#doc-html-pages","title":"Doc HTML Pages","text":"

To read the documentation as HTML pages, run the following code (you need Python on your computer)

pip install mkdocs-material mdx_truly_sane_lists\nmkdocs serve\n

To just generate HTML pages that you can host anywhere, run mkdocs build

"},{"location":"hardis/doc/project2markdown/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) diff-only boolean Generate documentation only for changed files (used for monitoring) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration with-history boolean Generate a markdown file with the history diff of the Flow"},{"location":"hardis/doc/project2markdown/#examples","title":"Examples","text":"
$ sf hardis:doc:project2markdown\n
$ sf hardis:doc:project2markdown --with-history\n
"},{"location":"hardis/doc/extract/permsetgroups/","title":"permsetgroups","text":""},{"location":"hardis/doc/extract/permsetgroups/#hardisdocextractpermsetgroups","title":"hardis:doc:extract:permsetgroups","text":""},{"location":"hardis/doc/extract/permsetgroups/#description","title":"Description","text":"

Generate markdown files with project documentation

"},{"location":"hardis/doc/extract/permsetgroups/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/doc/extract/permsetgroups/#examples","title":"Examples","text":"
$ sf hardis:doc:extract:permsetgroups\n
"},{"location":"hardis/doc/plugin/generate/","title":"generate","text":""},{"location":"hardis/doc/plugin/generate/#hardisdocplugingenerate","title":"hardis:doc:plugin:generate","text":""},{"location":"hardis/doc/plugin/generate/#description","title":"Description","text":"

Generate Markdown documentation ready for HTML conversion with mkdocs

After the first run, you need to update manually:

  • mkdocs.yml
  • .github/workflows/build-deploy-docs.yml
  • docs/javascripts/gtag.js , if you want Google Analytics tracking

Then, activate Github pages, with \"gh_pages\" as target branch

At each merge into master/main branch, the GitHub Action build-deploy-docs will rebuild documentation and publish it in GitHub pages

"},{"location":"hardis/doc/plugin/generate/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/doc/plugin/generate/#examples","title":"Examples","text":"
$ sf hardis:doc:plugin:generate\n
"},{"location":"hardis/git/pull-requests/extract/","title":"extract","text":""},{"location":"hardis/git/pull-requests/extract/#hardisgitpull-requestsextract","title":"hardis:git:pull-requests:extract","text":""},{"location":"hardis/git/pull-requests/extract/#description","title":"Description","text":"

Extract pull requests with filtering criteria

"},{"location":"hardis/git/pull-requests/extract/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. min-date-m option Minimum date for PR outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required status-x option Status of the PR openmergedabandoned target-branch-t option Target branch of PRs websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/git/pull-requests/extract/#examples","title":"Examples","text":"
$ sf hardis:git:pull-requests:extract\n
$ sf hardis:git:pull-requests:extract --target-branch main --status merged\n
"},{"location":"hardis/lint/access/","title":"access","text":""},{"location":"hardis/lint/access/#hardislintaccess","title":"hardis:lint:access","text":""},{"location":"hardis/lint/access/#description","title":"Description","text":"

Check if elements(apex class and field) are at least in one permission set

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/lint/access/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) elementsignored-e option Ignore specific elements separated by commas flags-dir option undefined folder-f option Root folder force-app ignorerights-i option Ignore permission sets or profiles json boolean Format output as json. outputfile-x option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/lint/access/#examples","title":"Examples","text":"
$ sf hardis:lint:access\n
$ sf hardis:lint:access -e \"ApexClass:ClassA, CustomField:Account.CustomField\"\n
$ sf hardis:lint:access -i \"PermissionSet:permissionSetA, Profile\"\n
"},{"location":"hardis/lint/metadatastatus/","title":"metadatastatus","text":""},{"location":"hardis/lint/metadatastatus/#hardislintmetadatastatus","title":"hardis:lint:metadatastatus","text":""},{"location":"hardis/lint/metadatastatus/#description","title":"Description","text":"

Check if elements (flows and validation rules) are inactive in the project

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/lint/metadatastatus/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/lint/metadatastatus/#examples","title":"Examples","text":"
$ sf hardis:lint:metadatastatus\n
"},{"location":"hardis/lint/missingattributes/","title":"missingattributes","text":""},{"location":"hardis/lint/missingattributes/#hardislintmissingattributes","title":"hardis:lint:missingattributes","text":""},{"location":"hardis/lint/missingattributes/#description","title":"Description","text":"

Check if elements(custom fields) aren't description

"},{"location":"hardis/lint/missingattributes/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/lint/missingattributes/#examples","title":"Examples","text":"
$ sf hardis:lint:missingattributes\n
"},{"location":"hardis/lint/unusedmetadatas/","title":"unusedmetadatas","text":""},{"location":"hardis/lint/unusedmetadatas/#hardislintunusedmetadatas","title":"hardis:lint:unusedmetadatas","text":""},{"location":"hardis/lint/unusedmetadatas/#description","title":"Description","text":"

Check if elements (custom labels and custom permissions) are used in the project

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/lint/unusedmetadatas/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/lint/unusedmetadatas/#examples","title":"Examples","text":"
$ sf hardis:lint:unusedmetadatas\n
"},{"location":"hardis/mdapi/deploy/","title":"deploy","text":""},{"location":"hardis/mdapi/deploy/#hardismdapideploy","title":"hardis:mdapi:deploy","text":""},{"location":"hardis/mdapi/deploy/#description","title":"Description","text":"

sfdx-hardis wrapper for sfdx force:mdapi:deploy that displays tips to solve deployment errors.

See documentation of Salesforce command

"},{"location":"hardis/mdapi/deploy/#parameters","title":"Parameters","text":"Name Type Description Default Required Options checkonly-c boolean checkOnly concise boolean concise debug boolean debug deploydir-d option deployDir flags-dir option undefined ignoreerrors boolean ignoreErrors ignorewarnings-g boolean ignoreWarnings json boolean Format output as json. purgeondelete boolean purgeOnDelete runtests-r option runTests singlepackage-s boolean singlePackage soapdeploy boolean soapDeploy target-org-o option undefined testlevel-l option testLevel NoTestRun NoTestRunRunSpecifiedTestsRunLocalTestsRunAllTestsInOrg validateddeployrequestid-q option validatedDeployRequestId verbose boolean verbose wait-w option wait 120 websocket option websocket zipfile-f option zipFile"},{"location":"hardis/mdapi/deploy/#examples","title":"Examples","text":""},{"location":"hardis/misc/purge-references/","title":"purge-references","text":""},{"location":"hardis/misc/purge-references/#hardismiscpurge-references","title":"hardis:misc:purge-references","text":""},{"location":"hardis/misc/purge-references/#description","title":"Description","text":"

Purge references to any string in org metadatas before a deployment.

For example, this can be handy if you need to change the type of a custom field from Master Detail to Lookup.

USE WITH EXTREME CAUTION AND CAREFULLY READ THE MESSAGES !

"},{"location":"hardis/misc/purge-references/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. references-r option Comma-separated list of references to find in metadatas skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/misc/purge-references/#examples","title":"Examples","text":"
$ sf hardis:misc:purge-references\n
"},{"location":"hardis/misc/toml2csv/","title":"toml2csv","text":""},{"location":"hardis/misc/toml2csv/#hardismisctoml2csv","title":"hardis:misc:toml2csv","text":""},{"location":"hardis/misc/toml2csv/#description","title":"Description","text":"

Split TOML file into distinct CSV files

"},{"location":"hardis/misc/toml2csv/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) filtersections-l option List of sections to process (if not set, all sections will be processed) flags-dir option undefined json boolean Format output as json. outputdir-z option Output directory skipauth boolean Skip authentication check when a default username is required skiptransfo-s boolean Do not apply transformation to input data target-org-o option undefined tomlfile-f option Input TOML file path transfoconfig-t option Path to JSON config file for mapping and transformation websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/misc/toml2csv/#examples","title":"Examples","text":"
$ sf hardis:misc:toml2csv --tomlfile 'D:/clients/toto/V1_full.txt' \n
$ sf hardis:misc:toml2csv --skiptransfo --tomlfile 'D:/clients/toto/V1_full.txt' \n
$ sf hardis:misc:toml2csv --skiptransfo --tomlfile 'D:/clients/toto/V1_full.txt' --outputdir 'C:/tmp/rrrr'\n
$ NODE_OPTIONS=--max_old_space_size=9096 sf hardis:misc:toml2csv --skiptransfo --tomlfile './input/V1.txt' --outputdir './output' --filtersections 'COMPTES,SOUS'\n
"},{"location":"hardis/org/connect/","title":"connect","text":""},{"location":"hardis/org/connect/#hardisorgconnect","title":"hardis:org:connect","text":""},{"location":"hardis/org/connect/#description","title":"Description","text":"

Connect to an org without setting it as default username, then proposes to open the org in web browser

"},{"location":"hardis/org/connect/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/connect/#examples","title":"Examples","text":"
$ sf hardis:org:connect\n
"},{"location":"hardis/org/create/","title":"create","text":""},{"location":"hardis/org/create/#hardisorgcreate","title":"hardis:org:create","text":""},{"location":"hardis/org/create/#description","title":"Description","text":"

Create and initialize sandbox org

"},{"location":"hardis/org/create/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/create/#examples","title":"Examples","text":"
$ sf hardis:org:create\n
"},{"location":"hardis/org/multi-org-query/","title":"multi-org-query","text":""},{"location":"hardis/org/multi-org-query/#hardisorgmulti-org-query","title":"hardis:org:multi-org-query","text":""},{"location":"hardis/org/multi-org-query/#description","title":"Description","text":"

Executes a SOQL query in multiple orgs and generate a single report from it

You can send a custom query using --query, or use one of the predefined queries using --query-template.

If you use the command from a CI/CD job, you must previously authenticate to the usernames present in --target-orgs.

"},{"location":"hardis/org/multi-org-query/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv query-q option SOQL Query to run on multiple orgs query-template-t option Use one of predefined SOQL Query templates active-usersall-users skipauth boolean Skip authentication check when a default username is required target-orgs-x option List of org usernames or aliases. websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/multi-org-query/#examples","title":"Examples","text":"
$ sf hardis:org:multi-org-query\n
$ sf hardis:org:multi-org-query --query \"SELECT Id,Username FROM User\"\n
$ sf hardis:org:multi-org-query --query \"SELECT Id,Username FROM User\" --target-orgs nico@cloudity.com nico@cloudity.com.preprod nico@cloudity.com.uat\n
$ sf hardis:org:multi-org-query --query-template active-users --target-orgs nico@cloudity.com nico@cloudity.com.preprod nico@cloudity.com.uat\n
"},{"location":"hardis/org/select/","title":"select","text":""},{"location":"hardis/org/select/#hardisorgselect","title":"hardis:org:select","text":""},{"location":"hardis/org/select/#description","title":"Description","text":"

Interactive org selection for user

"},{"location":"hardis/org/select/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) devhub-h boolean Also connect associated DevHub flags-dir option undefined json boolean Format output as json. scratch-s boolean Select scratch org related to default DevHub skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/select/#examples","title":"Examples","text":"
$ sf hardis:org:select\n
"},{"location":"hardis/org/community/update/","title":"update","text":""},{"location":"hardis/org/community/update/#hardisorgcommunityupdate","title":"hardis:org:community:update","text":""},{"location":"hardis/org/community/update/#description","title":"Description","text":"

Activate or deactivate a community by changing it's status:

  • Live
  • DownForMaintenance
"},{"location":"hardis/org/community/update/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. name-n option List of Networks Names that you want to update, separated by comma status-s option New status for the community, available values are: Live, DownForMaintenance target-org-o option undefined"},{"location":"hardis/org/community/update/#examples","title":"Examples","text":"
$ sf hardis:org:community:update --name 'MyNetworkName' --status DownForMaintenance\n
$ sf hardis:org:community:update --name 'MyNetworkName,MySecondNetworkName' --status Live\n
"},{"location":"hardis/org/configure/data/","title":"data","text":""},{"location":"hardis/org/configure/data/#hardisorgconfiguredata","title":"hardis:org:configure:data","text":""},{"location":"hardis/org/configure/data/#description","title":"Description","text":"

Configure Data Export/Import with a SFDX Data Loader Project

See article:

"},{"location":"hardis/org/configure/data/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/configure/data/#examples","title":"Examples","text":"
$ sf hardis:org:configure:data\n
"},{"location":"hardis/org/configure/files/","title":"files","text":""},{"location":"hardis/org/configure/files/#hardisorgconfigurefiles","title":"hardis:org:configure:files","text":""},{"location":"hardis/org/configure/files/#description","title":"Description","text":"

Configure export of file attachments from a Salesforce org

See article below

"},{"location":"hardis/org/configure/files/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/configure/files/#examples","title":"Examples","text":"
$ sf hardis:org:configure:files\n
"},{"location":"hardis/org/configure/monitoring/","title":"monitoring","text":""},{"location":"hardis/org/configure/monitoring/#hardisorgconfiguremonitoring","title":"hardis:org:configure:monitoring","text":""},{"location":"hardis/org/configure/monitoring/#description","title":"Description","text":"

Configure monitoring of an org

"},{"location":"hardis/org/configure/monitoring/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. orginstanceurl option Org instance url (technical param, do not use manually) skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/configure/monitoring/#examples","title":"Examples","text":"
$ sf hardis:org:configure:monitoring\n
"},{"location":"hardis/org/data/delete/","title":"delete","text":""},{"location":"hardis/org/data/delete/#hardisorgdatadelete","title":"hardis:org:data:delete","text":""},{"location":"hardis/org/data/delete/#description","title":"Description","text":"

Delete records in multiple objects using SFDMU Workspace

If you need to run this command in production, you need to:

  • define runnableInProduction in export.json
  • define sfdmuCanModify: YOUR_INSTANCE_URL in config/branches/.sfdx-hardis.YOUR_BRANCH.yml
"},{"location":"hardis/org/data/delete/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. path-p option Path to the sfdmu workspace folder skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/data/delete/#examples","title":"Examples","text":"
$ sf hardis:org:data:delete\n
"},{"location":"hardis/org/data/export/","title":"export","text":""},{"location":"hardis/org/data/export/#hardisorgdataexport","title":"hardis:org:data:export","text":""},{"location":"hardis/org/data/export/#description","title":"Description","text":"

Export data from an org using a SFDX Data Loader Project

See article:

"},{"location":"hardis/org/data/export/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. path-p option Path to the sfdmu workspace folder skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/data/export/#examples","title":"Examples","text":"
$ sf hardis:org:data:export\n
"},{"location":"hardis/org/data/import/","title":"import","text":""},{"location":"hardis/org/data/import/#hardisorgdataimport","title":"hardis:org:data:import","text":""},{"location":"hardis/org/data/import/#description","title":"Description","text":"

Import/Load data in an org using a SFDX Data Loader Project

If you need to run this command in a production org, you need to either:

  • Define sfdmuCanModify in your .sfdx-hardis.yml config file. (Example: sfdmuCanModify: prod-instance.my.salesforce.com)
  • Define an environment variable SFDMU_CAN_MODIFY. (Example: SFDMU_CAN_MODIFY=prod-instance.my.salesforce.com)

See article:

"},{"location":"hardis/org/data/import/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. path-p option Path to the sfdmu workspace folder skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/data/import/#examples","title":"Examples","text":"
$ sf hardis:org:data:import\n
"},{"location":"hardis/org/diagnose/audittrail/","title":"audittrail","text":""},{"location":"hardis/org/diagnose/audittrail/#hardisorgdiagnoseaudittrail","title":"hardis:org:diagnose:audittrail","text":""},{"location":"hardis/org/diagnose/audittrail/#description","title":"Description","text":"

Export Audit trail into a CSV file with selected criteria, and highlight suspect actions

Regular setup actions performed in major orgs are filtered.

  • \"\"
    • createScratchOrg
    • changedsenderemail
    • deleteScratchOrg
    • loginasgrantedtopartnerbt
  • Certificate and Key Management
    • insertCertificate
  • Custom App Licenses
    • addeduserpackagelicense
    • granteduserpackagelicense
  • Customer Portal
    • createdcustomersuccessuser
  • Currency
    • updateddatedexchrate
  • Data Management
    • queueMembership
  • Email Administration
    • dkimRotationPreparationSuccessful
    • dkimRotationSuccessful
  • Groups
    • groupMembership
  • Holidays
    • holiday_insert
  • Inbox mobile and legacy desktop apps
    • enableSIQUserNonEAC
  • Manage Users
    • activateduser
    • createduser
    • changedcommunitynickname
    • changedemail
    • changedfederationid
    • changedpassword
    • changedinteractionuseroffon
    • changedinteractionuseronoff
    • changedmarketinguseroffon
    • changedmarketinguseronoff
    • changedprofileforuser
    • changedprofileforusercusttostd
    • changedprofileforuserstdtocust
    • changedroleforusertonone
    • changedroleforuser
    • changedroleforuserfromnone
    • changedUserEmailVerifiedStatusUnverified
    • changedUserEmailVerifiedStatusVerified
    • changedUserPhoneNumber
    • changedUserPhoneVerifiedStatusUnverified
    • deactivateduser
    • deleteAuthenticatorPairing
    • deleteTwoFactorInfo2
    • deleteTwoFactorTempCode
    • frozeuser
    • insertAuthenticatorPairing
    • insertTwoFactorInfo2
    • insertTwoFactorTempCode
    • lightningloginenroll
    • PermSetAssign
    • PermSetGroupAssign
    • PermSetGroupUnassign
    • PermSetLicenseAssign
    • PermSetUnassign
    • PermSetLicenseUnassign
    • registeredUserPhoneNumber
    • resetpassword
    • suOrgAdminLogin
    • suOrgAdminLogout
    • unfrozeuser
    • useremailchangesent
  • Mobile Administration
    • assigneduserstomobileconfig
  • Reporting Snapshots
    • createdReportJob
    • deletedReportJob
  • Sandboxes
    • DeleteSandbox

By default, deployment user defined in .sfdx-hardis.yml targetUsername property will be excluded.

You can define additional users to exclude in .sfdx-hardis.yml monitoringExcludeUsernames property.

You can also add more sections / actions considered as not suspect using property monitoringAllowedSectionsActions

Example:

monitoringExcludeUsernames:\n  - deploymentuser@cloudity.com\n  - marketingcloud@cloudity.com\n  - integration-user@cloudity.com\n\nmonitoringAllowedSectionsActions:\n  \"Some section\": [] // Will ignore all actions from such section\n  \"Some other section\": [\"actionType1\",\"actionType2\",\"actionType3\"] // Will ignore only those 3 actions from section \"Some other section\". Other actions in the same section will be considered as suspect.\n

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/org/diagnose/audittrail/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) excludeusers-e option Comma-separated list of usernames to exclude flags-dir option undefined json boolean Format output as json. lastndays-t option Number of days to extract from today (included) outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/diagnose/audittrail/#examples","title":"Examples","text":"
$ sf hardis:org:diagnose:audittrail\n
$ sf hardis:org:diagnose:audittrail --excludeusers baptiste@titi.com\n
$ sf hardis:org:diagnose:audittrail --excludeusers baptiste@titi.com,bertrand@titi.com\n
$ sf hardis:org:diagnose:audittrail --lastndays 5\n
"},{"location":"hardis/org/diagnose/instanceupgrade/","title":"instanceupgrade","text":""},{"location":"hardis/org/diagnose/instanceupgrade/#hardisorgdiagnoseinstanceupgrade","title":"hardis:org:diagnose:instanceupgrade","text":""},{"location":"hardis/org/diagnose/instanceupgrade/#description","title":"Description","text":"

Get the date when the org instance will be upgraded (to Spring, Summer or Winter)

"},{"location":"hardis/org/diagnose/instanceupgrade/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/diagnose/instanceupgrade/#examples","title":"Examples","text":"
$ sf hardis:org:diagnose:instanceupgrade\n
"},{"location":"hardis/org/diagnose/legacyapi/","title":"legacyapi","text":""},{"location":"hardis/org/diagnose/legacyapi/#hardisorgdiagnoselegacyapi","title":"hardis:org:diagnose:legacyapi","text":""},{"location":"hardis/org/diagnose/legacyapi/#description","title":"Description","text":"

Checks if an org uses retired or someday retired API version

See article below

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/org/diagnose/legacyapi/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) eventtype-e option Type of EventLogFile event to analyze ApiTotalUsage flags-dir option undefined json boolean Format output as json. limit-l option Number of latest EventLogFile events to analyze 999 outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/diagnose/legacyapi/#examples","title":"Examples","text":"
$ sf hardis:org:diagnose:legacyapi\n
$ sf hardis:org:diagnose:legacyapi -u hardis@myclient.com\n
$ sf hardis:org:diagnose:legacyapi --outputfile 'c:/path/to/folder/legacyapi.csv'\n
$ sf hardis:org:diagnose:legacyapi -u hardis@myclient.com --outputfile ./tmp/legacyapi.csv\n
"},{"location":"hardis/org/diagnose/licenses/","title":"licenses","text":""},{"location":"hardis/org/diagnose/licenses/#hardisorgdiagnoselicenses","title":"hardis:org:diagnose:licenses","text":""},{"location":"hardis/org/diagnose/licenses/#description","title":"Description","text":"

Mostly used for monitoring (Grafana) but you can also use it manually :)

"},{"location":"hardis/org/diagnose/licenses/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined usedonly-u boolean Filter to have only used licenses websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/diagnose/licenses/#examples","title":"Examples","text":"
$ sf hardis:org:diagnose:licenses\n
"},{"location":"hardis/org/diagnose/releaseupdates/","title":"releaseupdates","text":""},{"location":"hardis/org/diagnose/releaseupdates/#hardisorgdiagnosereleaseupdates","title":"hardis:org:diagnose:releaseupdates","text":""},{"location":"hardis/org/diagnose/releaseupdates/#description","title":"Description","text":"

Export Release Updates into a CSV file with selected criteria, and highlight Release Updates that should be checked.

Before publishing Breaking Changes \u274c, Salesforce announce them in the setup menu Release Updates

\u26a0\ufe0f Some of them are very important, because if you don't make the related upgrades in time (ex: before Winter 25) , your production org can crash !

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/org/diagnose/releaseupdates/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/diagnose/releaseupdates/#examples","title":"Examples","text":"
$ sf hardis:org:diagnose:releaseupdates\n
"},{"location":"hardis/org/diagnose/unused-apex-classes/","title":"unused-apex-classes","text":""},{"location":"hardis/org/diagnose/unused-apex-classes/#hardisorgdiagnoseunused-apex-classes","title":"hardis:org:diagnose:unused-apex-classes","text":""},{"location":"hardis/org/diagnose/unused-apex-classes/#description","title":"Description","text":"

List all async Apex classes (Batch,Queueable,Schedulable) that has not been called for more than 365 days.

The result class list probably can be removed from the project, and that will improve your test classes performances :)

The number of unused day is overridable using --days option.

The command uses queries on AsyncApexJob and CronTrigger technical tables to build the result.

Apex Classes CreatedBy and CreatedOn fields are calculated from MIN(date from git, date from org)

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/org/diagnose/unused-apex-classes/#parameters","title":"Parameters","text":"Name Type Description Default Required Options days-t option Extracts the users that have been inactive for the amount of days specified. In CI, default is 180 days debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/diagnose/unused-apex-classes/#examples","title":"Examples","text":"
$ sf hardis:org:diagnose:unused-apex-classes\n
$ sf hardis:org:diagnose:unused-apex-classes --days 700\n
"},{"location":"hardis/org/diagnose/unused-connected-apps/","title":"unused-connected-apps","text":""},{"location":"hardis/org/diagnose/unused-connected-apps/#hardisorgdiagnoseunused-connected-apps","title":"hardis:org:diagnose:unused-connected-apps","text":""},{"location":"hardis/org/diagnose/unused-connected-apps/#description","title":"Description","text":"

Request objects ConnectedApp, LoginHistory and OAuthToken to find which connected apps might not be used anymore, and could be deleted for security / technical debt reasons.

Check with Connected Apps metadatas if the app is still active (inactive = \"Admin Users are pre-authorized + no Profile or Permission set assigned\")

The following default Salesforce Connected Apps are ignored:

  • Ant Migration Tool
  • Chatter Desktop
  • Chatter Mobile for BlackBerry
  • Force.com IDE
  • OIQ_Integration
  • Salesforce CLI
  • Salesforce Files
  • Salesforce Mobile Dashboards
  • Salesforce Touch
  • Salesforce for Outlook
  • SalesforceA
  • SalesforceA for Android
  • SalesforceA for iOS
  • SalesforceDX Namespace Registry
  • SalesforceIQ

You can add more ignored apps by defining a comma-separated list of names in variable ALLOWED_INACTIVE_CONNECTED_APPS

Example: ALLOWED_INACTIVE_CONNECTED_APPS=My App 1,My App 2, My App 3

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/org/diagnose/unused-connected-apps/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/diagnose/unused-connected-apps/#examples","title":"Examples","text":"
$ sf hardis:org:diagnose:unused-connected-apps\n
"},{"location":"hardis/org/diagnose/unusedlicenses/","title":"unusedlicenses","text":""},{"location":"hardis/org/diagnose/unusedlicenses/#hardisorgdiagnoseunusedlicenses","title":"hardis:org:diagnose:unusedlicenses","text":""},{"location":"hardis/org/diagnose/unusedlicenses/#description","title":"Description","text":"

When you assign a Permission Set to a user, and that this Permission Set is related to a Permission Set License, a Permission Set License Assignment is automatically created for the user.

But when you unassign this Permission Set from the user, the Permission Set License Assignment is not deleted.

This leads that you can be charged for Permission Set Licenses that are not used !

This command detects such useless Permission Set Licenses Assignments and suggests to delete them.

Many thanks to Vincent Finet for the inspiration during his great speaker session at French Touch Dreamin '23, and his kind agreement for reusing such inspiration in this command :)

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/org/diagnose/unusedlicenses/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/diagnose/unusedlicenses/#examples","title":"Examples","text":"
$ sf hardis:org:diagnose:unusedlicenses\n
$ sf hardis:org:diagnose:unusedlicenses --fix\n
"},{"location":"hardis/org/diagnose/unusedusers/","title":"unusedusers","text":""},{"location":"hardis/org/diagnose/unusedusers/#hardisorgdiagnoseunusedusers","title":"hardis:org:diagnose:unusedusers","text":""},{"location":"hardis/org/diagnose/unusedusers/#description","title":"Description","text":"

Efficient user management is vital in Salesforce to ensure resources are optimized and costs are controlled. However, inactive or unused user accounts can often go unnoticed, leading to wasted licenses and potential security risks. This tool addresses this challenge by enabling administrators to identify users who haven't logged in within a specified period.

By analyzing user login activity and last login timestamps, this feature highlights inactive user accounts, allowing administrators to take appropriate action. Whether it's deactivating dormant accounts, freeing up licenses, or ensuring compliance with security policies, this functionality empowers administrators to maintain a lean and secure Salesforce environment.

licensetypes values are the following:

  • all-crm: SFDC,AUL,AUL1,AULL_IGHT
  • all-paying: SFDC,AUL,AUL1,AULL_IGHT,PID_Customer_Community,PID_Customer_Community_Login,PID_Partner_Community,PID_Partner_Community_Login

Note: You can see the full list of available license identifiers in Salesforce Documentation

Use --returnactiveusers to revert the command and retrieve active users that has logged in during the period.

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/org/diagnose/unusedusers/#parameters","title":"Parameters","text":"Name Type Description Default Required Options days-t option Extracts the users that have been inactive for the amount of days specified. In CI, default is 180 days debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. licenseidentifiers-i option Comma-separated list of license identifiers, in case licensetypes is not used.. Identifiers available at https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_userlicense.htm licensetypes-l option Type of licenses to check. If set, do not use licenseidentifiers option. In CI, default is all-crm allall-crmall-paying outputfile-f option Force the path and name of output report file. Must end with .csv returnactiveusers boolean Inverts the command by returning the active users skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/diagnose/unusedusers/#examples","title":"Examples","text":"
$ sf hardis:org:diagnose:unusedusers\n
$ sf hardis:org:diagnose:unusedusers --days 365\n
$ sf hardis:org:diagnose:unusedusers --days 60 --licensetypes all-crm\n
$ sf hardis:org:diagnose:unusedusers --days 60 --licenseidentifiers SFDC,AUL,AUL1\n
$ sf hardis:org:diagnose:unusedusers --days 60 --licensetypes all-crm --returnactiveusers\n
"},{"location":"hardis/org/files/export/","title":"export","text":""},{"location":"hardis/org/files/export/#hardisorgfilesexport","title":"hardis:org:files:export","text":""},{"location":"hardis/org/files/export/#description","title":"Description","text":"

Export file attachments from a Salesforce org

See article below

"},{"location":"hardis/org/files/export/#parameters","title":"Parameters","text":"Name Type Description Default Required Options chunksize-c option Number of records to add in a chunk before it is processed 1000 debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. path-p option Path to the file export project polltimeout-t option Timeout in MS for Bulk API calls 300000 skipauth boolean Skip authentication check when a default username is required startchunknumber-s option Chunk number to start from target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/files/export/#examples","title":"Examples","text":"
$ sf hardis:org:files:export\n
"},{"location":"hardis/org/files/import/","title":"import","text":""},{"location":"hardis/org/files/import/#hardisorgfilesimport","title":"hardis:org:files:import","text":""},{"location":"hardis/org/files/import/#description","title":"Description","text":"

Import file attachments into a Salesforce org

See article below to see how to Export them.

"},{"location":"hardis/org/files/import/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. overwrite-f boolean Override existing files (doubles the number of API calls) path-p option Path to the file export project skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/files/import/#examples","title":"Examples","text":"
$ sf hardis:org:files:import\n
"},{"location":"hardis/org/fix/listviewmine/","title":"listviewmine","text":""},{"location":"hardis/org/fix/listviewmine/#hardisorgfixlistviewmine","title":"hardis:org:fix:listviewmine","text":""},{"location":"hardis/org/fix/listviewmine/#description","title":"Description","text":"

Fix listviews whose scope Mine has been replaced by Everything

List of ListViews can be:

  • read from .sfdx-hardis.yml file in property listViewsToSetToMine
  • sent in argument listviews

Note: property listViewsToSetToMine can be auto-generated by command hardis:work:save if .sfdx-hardis.yml contains the following configuration

autoCleanTypes:\n  - listViewsMine\n
  • Example of sfdx-hardis.yml property listViewsToSetToMine:
listViewsToSetToMine:\n  - \"force-app/main/default/objects/Operation__c/listViews/MyCurrentOperations.listView-meta.xml\"\n  - \"force-app/main/default/objects/Operation__c/listViews/MyFinalizedOperations.listView-meta.xml\"\n  - \"force-app/main/default/objects/Opportunity/listViews/Default_Opportunity_Pipeline.listView-meta.xml\"\n  - \"force-app/main/default/objects/Opportunity/listViews/MyCurrentSubscriptions.listView-meta.xml\"\n  - \"force-app/main/default/objects/Opportunity/listViews/MySubscriptions.listView-meta.xml\"\n  - \"force-app/main/default/objects/Account/listViews/MyActivePartners.listView-meta.xml\"\n
  • If manually written, this could also be:
listViewsToSetToMine:\n  - \"Operation__c:MyCurrentOperations\"\n  - \"Operation__c:MyFinalizedOperations\"\n  - \"Opportunity:Default_Opportunity_Pipeline\"\n  - \"Opportunity:MyCurrentSubscriptions\"\n  - \"Opportunity:MySubscriptions\"\n  - \"Account:MyActivePartners\"\n

Troubleshooting: if you need to run this command from an alpine-linux based docker image, use this workaround in your dockerfile:

# Do not use puppeteer embedded chromium\nRUN apk add --update --no-cache chromium\nENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=\"true\"\nENV CHROMIUM_PATH=\"/usr/bin/chromium-browser\"\nENV PUPPETEER_EXECUTABLE_PATH=\"$\\{CHROMIUM_PATH}\" // remove \\ before {\n
"},{"location":"hardis/org/fix/listviewmine/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. listviews-l option Comma-separated list of listviews following format Object:ListViewName Example: Contact:MyContacts,Contact:MyActiveContacts,Opportunity:MYClosedOpportunities skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/fix/listviewmine/#examples","title":"Examples","text":"
$ sf hardis:org:fix:listviewmine\n
$ sf hardis:org:fix:listviewmine --listviews Opportunity:MySubscriptions,Account:MyActivePartners\n
"},{"location":"hardis/org/generate/packagexmlfull/","title":"packagexmlfull","text":""},{"location":"hardis/org/generate/packagexmlfull/#hardisorggeneratepackagexmlfull","title":"hardis:org:generate:packagexmlfull","text":""},{"location":"hardis/org/generate/packagexmlfull/#description","title":"Description","text":"

Generates full org package.xml, including managed items

"},{"location":"hardis/org/generate/packagexmlfull/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile option Output package.xml file skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/generate/packagexmlfull/#examples","title":"Examples","text":"
$ sf hardis:org:generate:packagexmlfull\n
$ sf hardis:org:generate:packagexmlfull --outputfile /tmp/packagexmlfull.xml\n
$ sf hardis:org:generate:packagexmlfull --target-org nico@example.com\n
"},{"location":"hardis/org/monitor/all/","title":"all","text":""},{"location":"hardis/org/monitor/all/#hardisorgmonitorall","title":"hardis:org:monitor:all","text":""},{"location":"hardis/org/monitor/all/#description","title":"Description","text":"

Monitor org, generate reports and sends notifications

You can disable some commands defining either a monitoringDisable property in .sfdx-hardis.yml, or a comma separated list in env variable MONITORING_DISABLE

Example in .sfdx-hardis.yml:

monitoringDisable:\n  - METADATA_STATUS\n  - MISSING_ATTRIBUTES\n  - UNUSED_METADATAS\n

Example in env var:

MONITORING_DISABLE=METADATA_STATUS,MISSING_ATTRIBUTES,UNUSED_METADATAS\n

A default list of monitoring commands is used, if you want to override it you can define property monitoringCommands in your .sfdx-hardis.yml file

Example:

monitoringCommands:\n  - title: My Custom command\n    command: sf my:custom:command\n  - title: My Custom command 2\n    command: sf my:other:custom:command\n

You can force the daily run of all commands by defining env var MONITORING_IGNORE_FREQUENCY=true

The default list of commands is the following:

Key Description Command Frequency AUDIT_TRAIL Detect suspect setup actions in major org sf hardis:org:diagnose:audittrail daily LEGACY_API Detect calls to deprecated API versions sf hardis:org:diagnose:legacyapi daily ORG_LIMITS Detect if org limits are close to be reached sf hardis:org:monitor:limits daily LICENSES Extract licenses information sf hardis:org:diagnose:licenses weekly LINT_ACCESS Detect custom elements with no access rights defined in permission sets sf hardis:lint:access weekly UNUSED_LICENSES Detect permission set licenses that are assigned to users that do not need them sf hardis:org:diagnose:unusedlicenses weekly UNUSED_USERS Detect active users without recent logins sf hardis:org:diagnose:unusedusers weekly ACTIVE_USERS Detect active users with recent logins sf hardis:org:diagnose:unusedusers --returnactiveusers weekly ORG_INFO Get org info + SF instance info + next major upgrade date sf hardis:org:diagnose:instanceupgrade weekly RELEASE_UPDATES Gather warnings about incoming and overdue Release Updates sf hardis:org:diagnose:releaseupdates weekly UNUSED_METADATAS Detect custom labels and custom permissions that are not in use sf hardis:lint:unusedmetadatas weekly UNUSED_APEX_CLASSES Detect unused Apex classes in an org sf hardis:org:diagnose:unused-apex-classes weekly CONNECTED_APPS Detect unused Connected Apps in an org sf hardis:org:diagnose:unused-connected-apps weekly METADATA_STATUS Detect inactive metadata sf hardis:lint:metadatastatus weekly MISSING_ATTRIBUTES Detect missing description on custom field sf hardis:lint:missingattributes weekly"},{"location":"hardis/org/monitor/all/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/monitor/all/#examples","title":"Examples","text":"
$ sf hardis:org:monitor:all\n
"},{"location":"hardis/org/monitor/backup/","title":"backup","text":""},{"location":"hardis/org/monitor/backup/#hardisorgmonitorbackup","title":"hardis:org:monitor:backup","text":""},{"location":"hardis/org/monitor/backup/#description","title":"Description","text":"

Retrieve sfdx sources in the context of a monitoring backup

The command exists in 2 modes: filtered(default & recommended) and full.

"},{"location":"hardis/org/monitor/backup/#filtered-mode-default-better-performances","title":"Filtered mode (default, better performances)","text":"

Automatically skips metadatas from installed packages with namespace.

You can remove more metadata types from backup, especially in case you have too many metadatas and that provokes a crash, using:

  • Manual update of manifest/package-skip-items.xml config file (then commit & push in the same branch)
  • Environment variable MONITORING_BACKUP_SKIP_METADATA_TYPES (example: MONITORING_BACKUP_SKIP_METADATA_TYPES=CustomLabel,StaticResource,Translation): that will be applied to all monitoring branches.
"},{"location":"hardis/org/monitor/backup/#full-mode","title":"Full mode","text":"

Activate it with --full parameter, or variable MONITORING_BACKUP_MODE_FULL=true

Ignores filters (namespaces items & manifest/package-skip-items.xml) to retrieve ALL metadatas, including those you might not care about (reports, translations...)

As we can retrieve only 10000 files by call, the list of all metadatas will be chunked to make multiple calls (and take more time than filtered mode)

  • if you use --full-apply-filters , manifest/package-skip-items.xml and MONITORING_BACKUP_SKIP_METADATA_TYPES filters will be applied anyway
  • if you use --exclude-namespaces , namespaced items will be ignored

With those both options, it's like if you are not using --full, but with chunked metadata download

"},{"location":"hardis/org/monitor/backup/#in-cicd","title":"In CI/CD","text":"

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/org/monitor/backup/#documentation","title":"Documentation","text":"

Doc generation (including visual flows) is triggered at the end of the command.

If you want to also upload HTML Documentation on your Salesforce Org as static resource, use variable SFDX_HARDIS_DOC_DEPLOY_TO_ORG=\"true\"

If Flow history doc always display a single state, you probably need to update your workflow configuration:

  • on Gitlab: Env variable GIT_FETCH_EXTRA_FLAGS: --depth 10000
  • on GitHub: fetch-depth: 0
  • on Azure: fetchDepth: \"0\"
  • on Bitbucket: step: clone: depth: full
"},{"location":"hardis/org/monitor/backup/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) exclude-namespaces-e boolean If mode --full is activated, exclude namespaced metadatas flags-dir option undefined full boolean Dot not take in account filtering using package-skip-items.xml and MONITORING_BACKUP_SKIP_METADATA_TYPES. Efficient but much much slower ! full-apply-filters-z boolean If mode --full is activated, apply filters of manifest/package-skip-items.xml and MONITORING_BACKUP_SKIP_METADATA_TYPES anyway json boolean Format output as json. max-by-chunk-m option If mode --full is activated, maximum number of metadatas in a package.xml chunk 3000 outputfile-f option Force the path and name of output report file. Must end with .csv skip-doc boolean Skip the generation of project documentation at the end of the command skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/monitor/backup/#examples","title":"Examples","text":"
$ sf hardis:org:monitor:backup\n
$ sf hardis:org:monitor:backup --full\n
$ sf hardis:org:monitor:backup --full --exclude-namespaces\n
$ sf hardis:org:monitor:backup --full --exclude-namespaces --full-apply-filters\n
"},{"location":"hardis/org/monitor/limits/","title":"limits","text":""},{"location":"hardis/org/monitor/limits/#hardisorgmonitorlimits","title":"hardis:org:monitor:limits","text":""},{"location":"hardis/org/monitor/limits/#description","title":"Description","text":"

Check limits of a SF org and send notifications about limits are superior to 50%, 75% or 100%.

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/org/monitor/limits/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. outputfile-f option Force the path and name of output report file. Must end with .csv skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/monitor/limits/#examples","title":"Examples","text":"
$ sf hardis:org:monitor:limits\n
"},{"location":"hardis/org/purge/apexlog/","title":"apexlog","text":""},{"location":"hardis/org/purge/apexlog/#hardisorgpurgeapexlog","title":"hardis:org:purge:apexlog","text":""},{"location":"hardis/org/purge/apexlog/#description","title":"Description","text":"

Purge apex logs in selected org

"},{"location":"hardis/org/purge/apexlog/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. prompt-z boolean Prompt for confirmation (true by default, use --no-prompt to skip) skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/purge/apexlog/#examples","title":"Examples","text":"
$ sf hardis:org:purge:apexlog\n
$ sf hardis:org:purge:apexlog --target-org nicolas.vuillamy@gmail.com\n
"},{"location":"hardis/org/purge/flow/","title":"flow","text":""},{"location":"hardis/org/purge/flow/#hardisorgpurgeflow","title":"hardis:org:purge:flow","text":""},{"location":"hardis/org/purge/flow/#description","title":"Description","text":"

Purge Obsolete flow versions to avoid the 50 max versions limit. Filters on Status and Name

"},{"location":"hardis/org/purge/flow/#parameters","title":"Parameters","text":"Name Type Description Default Required Options allowpurgefailure-f boolean Allows purges to fail without exiting with 1. Use --no-allowpurgefailure to disable debug-d boolean Activate debug mode (more logs) delete-flow-interviews-w boolean If the presence of Flow interviews prevent to delete flows versions, delete them before retrying to delete flow versions flags-dir option undefined instanceurl-r option URL of org instance https://login.salesforce.com json boolean Format output as json. name-n option Filter according to Name criteria prompt-z boolean Prompt for confirmation (true by default, use --no-prompt to skip) skipauth boolean Skip authentication check when a default username is required status-s option Filter according to Status criteria target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/purge/flow/#examples","title":"Examples","text":"
$ sf hardis:org:purge:flow\n
$ sf hardis:org:purge:flow --target-org nicolas.vuillamy@gmail.com --no-prompt --delete-flow-interviews\n
$ sf hardis:org:purge:flow --target-org nicolas.vuillamy@gmail.com --status \"Obsolete,Draft,InvalidDraft\" --name TestFlow\n
"},{"location":"hardis/org/retrieve/packageconfig/","title":"packageconfig","text":""},{"location":"hardis/org/retrieve/packageconfig/#hardisorgretrievepackageconfig","title":"hardis:org:retrieve:packageconfig","text":""},{"location":"hardis/org/retrieve/packageconfig/#description","title":"Description","text":"

Retrieve package configuration from an org

"},{"location":"hardis/org/retrieve/packageconfig/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/retrieve/packageconfig/#examples","title":"Examples","text":"
$ sf hardis:org:retrieve:packageconfig\n
sf hardis:org:retrieve:packageconfig -u myOrg\n
"},{"location":"hardis/org/retrieve/sources/analytics/","title":"analytics","text":""},{"location":"hardis/org/retrieve/sources/analytics/#hardisorgretrievesourcesanalytics","title":"hardis:org:retrieve:sources:analytics","text":""},{"location":"hardis/org/retrieve/sources/analytics/#description","title":"Description","text":"

Retrieve all CRM Analytics sources from an org, with workarounds for SFDX bugs

"},{"location":"hardis/org/retrieve/sources/analytics/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/retrieve/sources/analytics/#examples","title":"Examples","text":"
$ sf hardis:org:retrieve:sources:analytics\n
"},{"location":"hardis/org/retrieve/sources/dx/","title":"dx","text":""},{"location":"hardis/org/retrieve/sources/dx/#hardisorgretrievesourcesdx","title":"hardis:org:retrieve:sources:dx","text":""},{"location":"hardis/org/retrieve/sources/dx/#description","title":"Description","text":"

Retrieve Salesforce DX project from org

"},{"location":"hardis/org/retrieve/sources/dx/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) filteredmetadatas-m option Comma separated list of Metadatas keys to remove from PackageXml file flags-dir option undefined folder-f option Folder . instanceurl-r option URL of org instance json boolean Format output as json. keepmetadatatypes-k option Comma separated list of metadatas types that will be the only ones to be retrieved shape-s boolean Updates project-scratch-def.json from org shape skipauth boolean Skip authentication check when a default username is required target-org-o option undefined tempfolder-t option Temporary folder ./tmp websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/retrieve/sources/dx/#examples","title":"Examples","text":"
$ sf hardis:org:retrieve:sources:dx\n
"},{"location":"hardis/org/retrieve/sources/dx2/","title":"dx2","text":""},{"location":"hardis/org/retrieve/sources/dx2/#hardisorgretrievesourcesdx2","title":"hardis:org:retrieve:sources:dx2","text":""},{"location":"hardis/org/retrieve/sources/dx2/#description","title":"Description","text":"

Retrieve Salesforce DX project from org

"},{"location":"hardis/org/retrieve/sources/dx2/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. packagexml-x option Path to package.xml file skipauth boolean Skip authentication check when a default username is required target-org-o option undefined template-t option sfdx-hardis package.xml Template name. ex: wave websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/retrieve/sources/dx2/#examples","title":"Examples","text":"
$ sf hardis:org:retrieve:sources:dx2\n
"},{"location":"hardis/org/retrieve/sources/metadata/","title":"metadata","text":""},{"location":"hardis/org/retrieve/sources/metadata/#hardisorgretrievesourcesmetadata","title":"hardis:org:retrieve:sources:metadata","text":""},{"location":"hardis/org/retrieve/sources/metadata/#description","title":"Description","text":"

Retrieve Salesforce DX project from org

"},{"location":"hardis/org/retrieve/sources/metadata/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined folder-f option Folder . includemanaged boolean Include items from managed packages instanceurl-r option URL of org instance json boolean Format output as json. packagexml-p option Path to package.xml manifest file skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/retrieve/sources/metadata/#examples","title":"Examples","text":"
$ sf hardis:org:retrieve:sources:metadata\n
$ SFDX_RETRIEVE_WAIT_MINUTES=200 sf hardis:org:retrieve:sources:metadata\n
"},{"location":"hardis/org/retrieve/sources/retrofit/","title":"retrofit","text":""},{"location":"hardis/org/retrieve/sources/retrofit/#hardisorgretrievesourcesretrofit","title":"hardis:org:retrieve:sources:retrofit","text":""},{"location":"hardis/org/retrieve/sources/retrofit/#description","title":"Description","text":"

Retrieve changes from org link to a ref branch not present in sources

This command need to be triggered from a branch that is connected to a SF org. It will then retrieve all changes not present in that branch sources, commit them and create a merge request against the default branch. If a merge request already exists, it will simply add a new commit.

Define the following properties in .sfdx-hardis.yml

- productionBranch : Name of the git branch that is corresponding to production org - retrofitBranch : Name of the git branch that will be used as merge request target

List of metadata to retrieve can be set in three way, in order of priority :

- CI_SOURCES_TO_RETROFIT: env variable (can be defined in CI context) - sourcesToRetrofit property in .sfdx-hardis.yml - Default list:

- CompactLayout\n- CustomApplication\n- CustomField\n- CustomLabel\n- CustomLabels\n- CustomMetadata\n- CustomObject\n- CustomObjectTranslation\n- CustomTab\n- DuplicateRule\n- EmailTemplate\n- FlexiPage\n- GlobalValueSet\n- Layout\n- ListView\n- MatchingRules\n- PermissionSet\n- RecordType\n- StandardValueSet\n- Translations\n- ValidationRule\n

You can also ignore some files even if they have been updated in production. To do that, define property retrofitIgnoredFiles in .sfdx-hardis.yml

Example of full retrofit configuration:

productionBranch: master\nretrofitBranch: preprod\nretrofitIgnoredFiles:\n- force-app/main/default/applications/MyApp.app-meta.xml\n- force-app/main/default/applications/MyOtherApp.app-meta.xml\n- force-app/main/default/flexipages/MyFlexipageContainingDashboards.flexipage-meta.xml\n
"},{"location":"hardis/org/retrieve/sources/retrofit/#parameters","title":"Parameters","text":"Name Type Description Default Required Options commit boolean If true, a commit will be performed after the retrofit commitmode option Defines if we commit all retrieved updates, or all updates including creations updated updatedall debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. productionbranch option Name of the git branch corresponding to the org we want to perform the retrofit on. Can be defined in productionBranch property in .sfdx-hardis.yml push boolean If true, a push will be performed after the retrofit pushmode option Defines if we send merge request options to git push arguments default defaultmergerequest retrofittargetbranch option Name of branch the merge request will have as target Can be defined in retrofitBranch property in .sfdx-hardis.yml skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/retrieve/sources/retrofit/#examples","title":"Examples","text":"
$ sf hardis:org:retrieve:sources:retrofit\n
sf hardis:org:retrieve:sources:retrofit --productionbranch master --commit --commitmode updated\n
sf hardis:org:retrieve:sources:retrofit --productionbranch master  --retrofitbranch preprod --commit --commitmode updated --push --pushmode mergerequest\n
"},{"location":"hardis/org/test/apex/","title":"apex","text":""},{"location":"hardis/org/test/apex/#hardisorgtestapex","title":"hardis:org:test:apex","text":""},{"location":"hardis/org/test/apex/#description","title":"Description","text":"

Run apex tests in Salesforce org

If following configuration is defined, it will fail if apex coverage target is not reached:

  • Env APEX_TESTS_MIN_COVERAGE_ORG_WIDE or .sfdx-hardis property apexTestsMinCoverageOrgWide
  • Env APEX_TESTS_MIN_COVERAGE_ORG_WIDE or .sfdx-hardis property apexTestsMinCoverageOrgWide

You can override env var SFDX_TEST_WAIT_MINUTES to wait more than 60 minutes.

This command is part of sfdx-hardis Monitoring and can output Grafana, Slack and MsTeams Notifications.

"},{"location":"hardis/org/test/apex/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined testlevel-l option Level of tests to apply to validate deployment RunLocalTests NoTestRunRunSpecifiedTestsRunLocalTestsRunAllTestsInOrg websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/test/apex/#examples","title":"Examples","text":"
$ sf hardis:org:test:apex\n
"},{"location":"hardis/org/user/activateinvalid/","title":"activateinvalid","text":""},{"location":"hardis/org/user/activateinvalid/#hardisorguseractivateinvalid","title":"hardis:org:user:activateinvalid","text":""},{"location":"hardis/org/user/activateinvalid/#description","title":"Description","text":"

Update sandbox users so their email is valid

Example: replaces toto@company.com.dev.invalid with toto@company.com.dev.invalid

See article below

"},{"location":"hardis/org/user/activateinvalid/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. profiles-p option Comma-separated list of profiles names that you want to reactive users assigned to and with a .invalid email skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/user/activateinvalid/#examples","title":"Examples","text":"
$ sf hardis:org:user:activateinvalid\n
$ sf hardis:org:user:activateinvalid --target-org my-user@myorg.com\n
$ sf hardis:org:user:activateinvalid --profiles 'System Administrator,MyCustomProfile' --target-org my-user@myorg.com\n
"},{"location":"hardis/org/user/freeze/","title":"freeze","text":""},{"location":"hardis/org/user/freeze/#hardisorguserfreeze","title":"hardis:org:user:freeze","text":""},{"location":"hardis/org/user/freeze/#description","title":"Description","text":"

Mass freeze users in org before a maintenance or go live

See user guide in the following article

https://medium.com/@dimitrimonge/freeze-unfreeze-users-during-salesforce-deployment-8a1488bf8dd3

"},{"location":"hardis/org/user/freeze/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) excludeprofiles-e option List of profiles that you want to NOT freeze, separated by commas flags-dir option undefined includeprofiles-p option List of profiles that you want to freeze, separated by commas json boolean Format output as json. maxuserdisplay-m option Maximum users to display in logs 100 name-n option Filter according to Name criteria skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/user/freeze/#examples","title":"Examples","text":"
$ sf hardis:org:user:freeze\n
$ sf hardis:org:user:freeze --target-org my-user@myorg.com\n
$ sf hardis:org:user:freeze --includeprofiles 'Standard'\n
$ sf hardis:org:user:freeze --excludeprofiles 'System Administrator,Some Other Profile'\n
"},{"location":"hardis/org/user/unfreeze/","title":"unfreeze","text":""},{"location":"hardis/org/user/unfreeze/#hardisorguserunfreeze","title":"hardis:org:user:unfreeze","text":""},{"location":"hardis/org/user/unfreeze/#description","title":"Description","text":"

Mass unfreeze users in org after a maintenance or go live

See user guide in the following article

https://medium.com/@dimitrimonge/freeze-unfreeze-users-during-salesforce-deployment-8a1488bf8dd3

"},{"location":"hardis/org/user/unfreeze/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) excludeprofiles-e option List of profiles that you want to NOT unfreeze, separated by commas flags-dir option undefined includeprofiles-p option List of profiles that you want to unfreeze, separated by commas json boolean Format output as json. maxuserdisplay-m option Maximum users to display in logs 100 name-n option Filter according to Name criteria skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/org/user/unfreeze/#examples","title":"Examples","text":"
$ sf hardis:org:user:unfreeze\n
$ sf hardis:org:user:unfreeze --target-org my-user@myorg.com\n
$ sf hardis:org:user:unfreeze --includeprofiles 'Standard'\n
$ sf hardis:org:user:unfreeze --excludeprofiles 'System Administrator,Some Other Profile'\n
"},{"location":"hardis/package/create/","title":"create","text":""},{"location":"hardis/package/create/#hardiscreate","title":"hardiscreate","text":""},{"location":"hardis/package/create/#description","title":"Description","text":"

Create a new package

"},{"location":"hardis/package/create/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/package/create/#examples","title":"Examples","text":"
$ sf hardis:package:create\n
"},{"location":"hardis/package/install/","title":"install","text":""},{"location":"hardis/package/install/#hardisinstall","title":"hardisinstall","text":""},{"location":"hardis/package/install/#description","title":"Description","text":"

Install a package in an org using its id (starting with 04t)

Assisted menu to propose to update installedPackages property in .sfdx-hardis.yml

"},{"location":"hardis/package/install/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined installationkey-k option installation key for key-protected package (default: null) json boolean Format output as json. package-p option Package Version Id to install (04t...) skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/package/install/#examples","title":"Examples","text":"
$ sf hardis:package:install\n
"},{"location":"hardis/package/mergexml/","title":"mergexml","text":""},{"location":"hardis/package/mergexml/#hardismergexml","title":"hardismergexml","text":""},{"location":"hardis/package/mergexml/#description","title":"Description","text":"

Select and merge package.xml files

"},{"location":"hardis/package/mergexml/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug boolean debug flags-dir option undefined folder-f option Root folder manifest json boolean Format output as json. packagexmls-p option Comma separated list of package.xml files to merge. Will be prompted to user if not provided pattern-x option Name criteria to list package.xml files //package.xml result-r option Result package.xml file name skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/package/mergexml/#examples","title":"Examples","text":"
$ sf hardis:package:mergexml\n
$ sf hardis:package:mergexml --folder packages --pattern /**/*.xml --result myMergedPackage.xml\n
$ sf hardis:package:mergexml --packagexmls \"config/mypackage1.xml,config/mypackage2.xml,config/mypackage3.xml\" --result myMergedPackage.xml\n
"},{"location":"hardis/package/version/create/","title":"create","text":""},{"location":"hardis/package/version/create/#hardisversioncreate","title":"hardisversion:create","text":""},{"location":"hardis/package/version/create/#description","title":"Description","text":"

Create a new version of an unlocked package

"},{"location":"hardis/package/version/create/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) deleteafter boolean Delete package version after creating it flags-dir option undefined install-i boolean Install package version on default org after generation installkey-k option Package installation key json boolean Format output as json. package-p option Package identifier that you want to use to generate a new package version skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/package/version/create/#examples","title":"Examples","text":"
$ sf hardis:package:version:create\n
"},{"location":"hardis/package/version/list/","title":"list","text":""},{"location":"hardis/package/version/list/#hardisversionlist","title":"hardisversion:list","text":""},{"location":"hardis/package/version/list/#description","title":"Description","text":"

List versions of unlocked package

"},{"location":"hardis/package/version/list/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/package/version/list/#examples","title":"Examples","text":"
$ sf hardis:package:version:list\n
"},{"location":"hardis/package/version/promote/","title":"promote","text":""},{"location":"hardis/package/version/promote/#hardisversionpromote","title":"hardisversion:promote","text":""},{"location":"hardis/package/version/promote/#description","title":"Description","text":"

Promote package(s) version(s): convert it from beta to released

"},{"location":"hardis/package/version/promote/#parameters","title":"Parameters","text":"Name Type Description Default Required Options auto-f boolean Auto-detect which versions of which packages need to be promoted debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/package/version/promote/#examples","title":"Examples","text":"
$ sf hardis:package:version:promote\n
$ sf hardis:package:version:promote --auto\n
"},{"location":"hardis/packagexml/append/","title":"append","text":""},{"location":"hardis/packagexml/append/#hardispackagexmlappend","title":"hardis:packagexml:append","text":""},{"location":"hardis/packagexml/append/#description","title":"Description","text":"

Append one or multiple package.xml files into a single one

"},{"location":"hardis/packagexml/append/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug boolean debug flags-dir option undefined json boolean Format output as json. outputfile-f option package.xml output file packagexmls-p option package.xml files path (separated by commas) websocket option websocket"},{"location":"hardis/packagexml/append/#examples","title":"Examples","text":"
$ sf hardis packagexml append -p package1.xml,package2.xml -o package3.xml\n
"},{"location":"hardis/packagexml/remove/","title":"remove","text":""},{"location":"hardis/packagexml/remove/#hardispackagexmlremove","title":"hardis:packagexml:remove","text":""},{"location":"hardis/packagexml/remove/#description","title":"Description","text":"

Removes the content of a package.xml file matching another package.xml file

"},{"location":"hardis/packagexml/remove/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug boolean debug flags-dir option undefined json boolean Format output as json. outputfile-f option package.xml output file packagexml-p option package.xml file to reduce removedonly-z boolean Use this flag to generate a package.xml with only removed items removepackagexml-r option package.xml file to use to filter input package.xml websocket option websocket"},{"location":"hardis/packagexml/remove/#examples","title":"Examples","text":"
$ sf hardis packagexml:remove -p package.xml -r destructiveChanges.xml -o my-reduced-package.xml\n
"},{"location":"hardis/project/create/","title":"create","text":""},{"location":"hardis/project/create/#hardisprojectcreate","title":"hardis:project:create","text":""},{"location":"hardis/project/create/#description","title":"Description","text":"

Create a new SFDX Project

"},{"location":"hardis/project/create/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/create/#examples","title":"Examples","text":"
$ sf hardis:project:create\n
"},{"location":"hardis/project/lint/","title":"lint","text":""},{"location":"hardis/project/lint/#hardisprojectlint","title":"hardis:project:lint","text":""},{"location":"hardis/project/lint/#description","title":"Description","text":"

Apply syntactic analysis (linters) on the repository sources, using Mega-Linter

"},{"location":"hardis/project/lint/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) fix-f boolean Apply linters fixes flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/lint/#examples","title":"Examples","text":"
$ sf hardis:project:lint\n
$ sf hardis:project:lint --fix\n
"},{"location":"hardis/project/audit/apiversion/","title":"apiversion","text":""},{"location":"hardis/project/audit/apiversion/#hardisprojectauditapiversion","title":"hardis:project:audit:apiversion","text":""},{"location":"hardis/project/audit/apiversion/#description","title":"Description","text":"

Audit API version

"},{"location":"hardis/project/audit/apiversion/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) failiferror-f boolean Fails (exit code 1) if an error is found flags-dir option undefined json boolean Format output as json. minimumapiversion-m option Minimum allowed API version 20 skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/audit/apiversion/#examples","title":"Examples","text":"
$ sf hardis:project:audit:apiversion\n
"},{"location":"hardis/project/audit/callincallout/","title":"callincallout","text":""},{"location":"hardis/project/audit/callincallout/#hardisprojectauditcallincallout","title":"hardis:project:audit:callincallout","text":""},{"location":"hardis/project/audit/callincallout/#description","title":"Description","text":"

Generate list of callIn and callouts from sfdx project

"},{"location":"hardis/project/audit/callincallout/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/audit/callincallout/#examples","title":"Examples","text":"
$ sf hardis:project:audit:callouts\n
"},{"location":"hardis/project/audit/duplicatefiles/","title":"duplicatefiles","text":""},{"location":"hardis/project/audit/duplicatefiles/#hardisprojectauditduplicatefiles","title":"hardis:project:audit:duplicatefiles","text":""},{"location":"hardis/project/audit/duplicatefiles/#description","title":"Description","text":"

Find duplicate files in sfdx folder (often from past @salesforce/cli bugs)

"},{"location":"hardis/project/audit/duplicatefiles/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. path-p option Root path to check /home/runner/work/sfdx-hardis/sfdx-hardis skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/audit/duplicatefiles/#examples","title":"Examples","text":"
$ sf hardis:project:audit:duplicatefiles\n
"},{"location":"hardis/project/audit/remotesites/","title":"remotesites","text":""},{"location":"hardis/project/audit/remotesites/#hardisprojectauditremotesites","title":"hardis:project:audit:remotesites","text":""},{"location":"hardis/project/audit/remotesites/#description","title":"Description","text":"

Generate list of remote sites

"},{"location":"hardis/project/audit/remotesites/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/audit/remotesites/#examples","title":"Examples","text":"
$ sf hardis:project:audit:remotesites\n
"},{"location":"hardis/project/clean/emptyitems/","title":"emptyitems","text":""},{"location":"hardis/project/clean/emptyitems/#hardisprojectcleanemptyitems","title":"hardis:project:clean:emptyitems","text":""},{"location":"hardis/project/clean/emptyitems/#description","title":"Description","text":"

Remove unwanted empty items within sfdx project sources

"},{"location":"hardis/project/clean/emptyitems/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined folder-f option Root folder force-app json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/emptyitems/#examples","title":"Examples","text":"
$ sf hardis:project:clean:emptyitems\n
"},{"location":"hardis/project/clean/filter-xml-content/","title":"filter-xml-content","text":""},{"location":"hardis/project/clean/filter-xml-content/#hardisprojectcleanfilter-xml-content","title":"hardis:project:clean:filter-xml-content","text":""},{"location":"hardis/project/clean/filter-xml-content/#description","title":"Description","text":"

Filter content of metadatas (XML) in order to be able to deploy only part of them on an org (See Example configuration)

When you perform deployments from one org to another, the features activated in the target org may not fit the content of the sfdx/metadata files extracted from the source org.

You may need to filter some elements in the XML files, for example in the Profiles

This script requires a filter-config.json file

"},{"location":"hardis/project/clean/filter-xml-content/#parameters","title":"Parameters","text":"Name Type Description Default Required Options configfile-c option Config JSON file path debug boolean debug flags-dir option undefined inputfolder-i option Input folder (default: \".\" ) json boolean Format output as json. outputfolder-f option Output folder (default: parentFolder + _xml_content_filtered) websocket option websocket"},{"location":"hardis/project/clean/filter-xml-content/#examples","title":"Examples","text":"
sf hardis:project:clean:filter-xml-content -i \"./mdapi_output\"\n
sf hardis:project:clean:filter-xml-content -i \"retrieveUnpackaged\"\n
"},{"location":"hardis/project/clean/flowpositions/","title":"flowpositions","text":""},{"location":"hardis/project/clean/flowpositions/#hardisprojectcleanflowpositions","title":"hardis:project:clean:flowpositions","text":""},{"location":"hardis/project/clean/flowpositions/#description","title":"Description","text":"

Replace all positions in Auto-Layout Flows by 0 to simplify conflicts management

As Flows are defined as Auto-Layout, the edition in Setup UI is not impacted.

Before:

<locationX>380</locationX>\n<locationY>259</locationY>\n

After:

<locationX>0</locationX>\n<locationY>0</locationY>\n

Can be automated at each hardis:work:save if flowPositions is added in .sfdx-hardis.yml autoCleanTypes property

Example in config/.sfdx-hardis.yml:

autoCleanTypes:\n  - destructivechanges\n  - flowPositions\n
"},{"location":"hardis/project/clean/flowpositions/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined folder-f option Root folder force-app json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/flowpositions/#examples","title":"Examples","text":"
$ sf hardis:project:clean:flowpositions\n
"},{"location":"hardis/project/clean/hiddenitems/","title":"hiddenitems","text":""},{"location":"hardis/project/clean/hiddenitems/#hardisprojectcleanhiddenitems","title":"hardis:project:clean:hiddenitems","text":""},{"location":"hardis/project/clean/hiddenitems/#description","title":"Description","text":"

Remove unwanted hidden items within sfdx project sources

"},{"location":"hardis/project/clean/hiddenitems/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined folder-f option Root folder force-app json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/hiddenitems/#examples","title":"Examples","text":"
$ sf hardis:project:clean:hiddenitems\n
"},{"location":"hardis/project/clean/listviews/","title":"listviews","text":""},{"location":"hardis/project/clean/listviews/#hardisprojectcleanlistviews","title":"hardis:project:clean:listviews","text":""},{"location":"hardis/project/clean/listviews/#description","title":"Description","text":"

Replace Mine by Everything in ListView, and log the replacements in sfdx-hardis.yml

"},{"location":"hardis/project/clean/listviews/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined folder-f option Root folder force-app json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/listviews/#examples","title":"Examples","text":"
$ sf hardis:project:clean:listviews\n
"},{"location":"hardis/project/clean/manageditems/","title":"manageditems","text":""},{"location":"hardis/project/clean/manageditems/#hardisprojectcleanmanageditems","title":"hardis:project:clean:manageditems","text":""},{"location":"hardis/project/clean/manageditems/#description","title":"Description","text":"

Remove unwanted managed items within sfdx project sources

"},{"location":"hardis/project/clean/manageditems/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined folder-f option Root folder force-app json boolean Format output as json. namespace-n option Namespace to remove skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/manageditems/#examples","title":"Examples","text":"
$ sf hardis:project:clean:manageditems --namespace crta\n
"},{"location":"hardis/project/clean/minimizeprofiles/","title":"minimizeprofiles","text":""},{"location":"hardis/project/clean/minimizeprofiles/#hardisprojectcleanminimizeprofiles","title":"hardis:project:clean:minimizeprofiles","text":""},{"location":"hardis/project/clean/minimizeprofiles/#description","title":"Description","text":"

Remove all profile attributes that exist on Permission Sets

It is a bad practice to define on Profiles elements that can be defined on Permission Sets.

Salesforce will deprecate such capability in Spring 26.

Don't wait for that, and use minimizeProfiles cleaning to automatically remove from Profiles any permission that exists on a Permission Set !

The following XML tags are removed automatically:

  • classAccesses
  • customMetadataTypeAccesses
  • externalDataSourceAccesses
  • fieldPermissions
  • objectPermissions
  • pageAccesses
  • userPermissions (except on Admin Profile)

You can override this list by defining a property minimizeProfilesNodesToRemove in your .sfdx-hardis.yml config file.

You can also skip profiles using property skipMinimizeProfiles

Example:

skipMinimizeProfiles\n  - MyClient Customer Community Login User\n  - MyClientPortail Profile\n
"},{"location":"hardis/project/clean/minimizeprofiles/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined folder-f option Root folder force-app json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/minimizeprofiles/#examples","title":"Examples","text":"
$ sf hardis:project:clean:minimizeprofiles\n
"},{"location":"hardis/project/clean/orgmissingitems/","title":"orgmissingitems","text":""},{"location":"hardis/project/clean/orgmissingitems/#hardisprojectcleanorgmissingitems","title":"hardis:project:clean:orgmissingitems","text":""},{"location":"hardis/project/clean/orgmissingitems/#description","title":"Description","text":"

Clean SFDX sources from items present neither in target org nor local package.xml

"},{"location":"hardis/project/clean/orgmissingitems/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined folder-f option Root folder force-app json boolean Format output as json. packagexmlfull-p option Path to packagexml used for cleaning. Must contain also standard CustomObject and CustomField elements. If not provided, it will be generated from a remote org packagexmltargetorg-t option Target org username or alias to build package.xml (SF CLI must be authenticated). If not provided, will be prompted to the user. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/orgmissingitems/#examples","title":"Examples","text":"
$ sf hardis:project:clean:orgmissingitems\n
"},{"location":"hardis/project/clean/references/","title":"references","text":""},{"location":"hardis/project/clean/references/#hardisprojectcleanreferences","title":"hardis:project:clean:references","text":""},{"location":"hardis/project/clean/references/#description","title":"Description","text":"

Remove unwanted references within sfdx project sources

"},{"location":"hardis/project/clean/references/#parameters","title":"Parameters","text":"Name Type Description Default Required Options config-c option Path to a JSON config file or a destructiveChanges.xml file debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required type-t option Cleaning type allcaseentitlementdashboardsdatadotcomdestructivechangeslocalfieldsproductrequestentitlementflowPositionssensitiveMetadatasminimizeProfiles websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/references/#examples","title":"Examples","text":"
$ sf hardis:project:clean:references\n
$ sf hardis:project:clean:references --type all\n
$ sf hardis:project:clean:references --config ./cleaning/myconfig.json\n
$ sf hardis:project:clean:references --config ./somefolder/myDestructivePackage.xml\n
"},{"location":"hardis/project/clean/retrievefolders/","title":"retrievefolders","text":""},{"location":"hardis/project/clean/retrievefolders/#hardisprojectcleanretrievefolders","title":"hardis:project:clean:retrievefolders","text":""},{"location":"hardis/project/clean/retrievefolders/#description","title":"Description","text":"

Retrieve dashboards, documents and report folders in DX sources. Use -u ORGALIAS

"},{"location":"hardis/project/clean/retrievefolders/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/retrievefolders/#examples","title":"Examples","text":"
$ sf hardis:project:clean:retrievefolders\n
"},{"location":"hardis/project/clean/sensitive-metadatas/","title":"sensitive-metadatas","text":""},{"location":"hardis/project/clean/sensitive-metadatas/#hardisprojectcleansensitive-metadatas","title":"hardis:project:clean:sensitive-metadatas","text":""},{"location":"hardis/project/clean/sensitive-metadatas/#description","title":"Description","text":"

Sensitive data like credentials and certificates are not supposed to be stored in Git, to avoid security breaches.

This command detects the related metadata and replaces their sensitive content by \"HIDDEN_BY_SFDX_HARDIS\"

Can be automated at each hardis:work:save if sensitiveMetadatas is added in .sfdx-hardis.yml autoCleanTypes property

Example in config/.sfdx-hardis.yml:

autoCleanTypes:\n  - destructivechanges\n  - sensitiveMetadatas\n
"},{"location":"hardis/project/clean/sensitive-metadatas/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined folder-f option Root folder force-app json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/sensitive-metadatas/#examples","title":"Examples","text":"
$ sf hardis:project:clean:sensitive-metadatas\n
"},{"location":"hardis/project/clean/standarditems/","title":"standarditems","text":""},{"location":"hardis/project/clean/standarditems/#hardisprojectcleanstandarditems","title":"hardis:project:clean:standarditems","text":""},{"location":"hardis/project/clean/standarditems/#description","title":"Description","text":"

Remove unwanted standard items within sfdx project sources

"},{"location":"hardis/project/clean/standarditems/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/standarditems/#examples","title":"Examples","text":"
$ sf hardis:project:clean:standarditems\n
"},{"location":"hardis/project/clean/systemdebug/","title":"systemdebug","text":""},{"location":"hardis/project/clean/systemdebug/#hardisprojectcleansystemdebug","title":"hardis:project:clean:systemdebug","text":""},{"location":"hardis/project/clean/systemdebug/#description","title":"Description","text":"

Clean System.debug() lines in APEX Code (classes and triggers)

"},{"location":"hardis/project/clean/systemdebug/#parameters","title":"Parameters","text":"Name Type Description Default Required Options delete-d boolean Delete lines with System.debug flags-dir option undefined folder-f option Root folder force-app json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/clean/systemdebug/#examples","title":"Examples","text":"
$ sf hardis:project:clean:systemdebug\n
"},{"location":"hardis/project/clean/xml/","title":"xml","text":""},{"location":"hardis/project/clean/xml/#hardisprojectcleanxml","title":"hardis:project:clean:xml","text":""},{"location":"hardis/project/clean/xml/#description","title":"Description","text":"

Remove XML elements using Glob patterns and XPath expressions

This can be very useful to avoid to always remove manually the same elements in the same XML file.

  • globpattern can be any glob pattern allowing to identify the XML files to update, for example /**/*.flexipage-meta.xml
  • xpath can be any xpath following the format //ns:PARENT-TAG-NAME//ns:TAG-NAME[contains(text(),'TAG-VALUE')]. If an element is found, the whole PARENT-TAG-NAME (with its subtree) will be removed.

Note: If globpattern and xpath are not sent, elements defined in property cleanXmlPatterns in .sfdx-hardis.yml config file will be used

"},{"location":"hardis/project/clean/xml/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined folder-f option Root folder force-app globpattern-p option Glob pattern to find files to clean. Ex: /*/.flexipage-meta.xml json boolean Format output as json. namespace-n option XML Namespace to use http://soap.sforce.com/2006/04/metadata skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration xpath-x option XPath to use to detect the elements to remove. Ex: //ns:flexiPageRegions//ns:name[contains(text(),'dashboardName')]"},{"location":"hardis/project/clean/xml/#examples","title":"Examples","text":"
$ sf hardis:project:clean:xml\n
$ sf hardis:project:clean:xml --globpattern \"/**/*.flexipage-meta.xml\" --xpath \"//ns:flexiPageRegions//ns:name[contains(text(),'dashboardName')]\"\n
"},{"location":"hardis/project/configure/auth/","title":"auth","text":""},{"location":"hardis/project/configure/auth/#hardisprojectconfigureauth","title":"hardis:project:configure:auth","text":""},{"location":"hardis/project/configure/auth/#description","title":"Description","text":"

Configure authentication from git branch to target org

"},{"location":"hardis/project/configure/auth/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) devhub-b boolean Configure project DevHub flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/configure/auth/#examples","title":"Examples","text":"
$ sf hardis:project:configure:auth\n
"},{"location":"hardis/project/convert/profilestopermsets/","title":"profilestopermsets","text":""},{"location":"hardis/project/convert/profilestopermsets/#hardisprojectconvertprofilestopermsets","title":"hardis:project:convert:profilestopermsets","text":""},{"location":"hardis/project/convert/profilestopermsets/#description","title":"Description","text":"

Creates permission sets from existing profiles, with id PS_PROFILENAME

"},{"location":"hardis/project/convert/profilestopermsets/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) except-e option List of filters flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/convert/profilestopermsets/#examples","title":"Examples","text":"
$ sf hardis:project:convert:profilestopermsets\n
"},{"location":"hardis/project/deploy/notify/","title":"notify","text":""},{"location":"hardis/project/deploy/notify/#hardisprojectdeploynotify","title":"hardis:project:deploy:notify","text":""},{"location":"hardis/project/deploy/notify/#description","title":"Description","text":"

Post notifications related to:

- Deployment simulation (use with --check-only) - Deployment process (to call only if your deployment is successful)

According to the integrations you configured, notifications can contain deployment information and Flow Visual Git Diff

- GitHub, Gitlab, Azure DevOps, Bitbucket comments on Pull Requests (including Flows Visual Git Diff) - Slack, Microsoft Teams, Email deployment summary after a successful deployment - JIRA tags and comments on tickets that just has been deployed

This command is for custom SF Cli pipelines, if you are a sfdx-hardis user, it is already embedded in sf hardis:deploy:smart.

You can also use sfdx-hardis wrapper commands of SF deployment commands

"},{"location":"hardis/project/deploy/notify/#parameters","title":"Parameters","text":"Name Type Description Default Required Options check-only-c boolean Use this option to send notifications from a Deployment simulation job debug-d boolean Activate debug mode (more logs) deploy-status-s option Send success, failure or unknown (default) to indicate if the deployment or deployment simulation is in success or not unknown validinvalidunknown flags-dir option undefined json boolean Format output as json. message-m option Custom message that you want to be added in notifications (string or markdown format) skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/deploy/notify/#examples","title":"Examples","text":"
$ sf hardis:project:deploy:notify --check-only --deploy-status valid --message \"This deployment check is valid\\n\\nYahooo !!\"\n
$ sf hardis:project:deploy:notify --check-only --deploy-status invalid --message \"This deployment check has failed !\\n\\Oh no !!\"\n
$ sf hardis:project:deploy:notify --deploy-status valid --message \"This deployment has been processed !\\n\\nYahooo !!\"\n
"},{"location":"hardis/project/deploy/quick/","title":"quick","text":""},{"location":"hardis/project/deploy/quick/#hardisprojectdeployquick","title":"hardis:project:deploy:quick","text":""},{"location":"hardis/project/deploy/quick/#description","title":"Description","text":"

sfdx-hardis wrapper for sf project deploy quick that displays tips to solve deployment errors.

Note: Use --json argument to have better results

See documentation of Salesforce command

"},{"location":"hardis/project/deploy/quick/#deployment-pre-or-post-commands","title":"Deployment pre or post commands","text":"

You can define command lines to run before or after a deployment, with parameters:

  • id: Unique Id for the command
  • label: Human readable label for the command
  • skipIfError: If defined to \"true\", the post-command won't be run if there is a deployment failure
  • context: Defines the context where the command will be run. Can be all (default), check-deployment-only or process-deployment-only
  • runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)

If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

Example:

commandsPreDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='deploy.github@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n\ncommandsPostDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to desired username\n    command: sf data update record --sobject User --where \"Username='admin-yser@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n  - id: someActionToRunJustOneTime\n    label: And to run only if deployment is success\n    command: sf sfdmu:run ...\n    skipIfError: true\n    context: process-deployment-only\n    runOnlyOnceByOrg: true\n
"},{"location":"hardis/project/deploy/quick/#parameters","title":"Parameters","text":"Name Type Description Default Required Options --job-id-i option job-id --use-most-recent-r boolean use-most-recent api-version-a option api-version async boolean async debug boolean debug flags-dir option undefined json boolean Format output as json. target-org-o option undefined tests option tests wait-w option wait 33"},{"location":"hardis/project/deploy/quick/#examples","title":"Examples","text":""},{"location":"hardis/project/deploy/simulate/","title":"simulate","text":""},{"location":"hardis/project/deploy/simulate/#hardisprojectdeploysimulate","title":"hardis:project:deploy:simulate","text":""},{"location":"hardis/project/deploy/simulate/#description","title":"Description","text":"

Simulate the deployment of a metadata in an org prompted to the user

For example, helps to solve the issue in a Permission Set without having to run a CI/CD job.

Used by VsCode Extension

"},{"location":"hardis/project/deploy/simulate/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required source-dir-f option Source file or directory to simulate the deployment target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/deploy/simulate/#examples","title":"Examples","text":"
$ sf hardis:project:deploy:simulate --source-dir force-app/defaut/main/permissionset/PS_Admin.permissionset-meta.xml\n
"},{"location":"hardis/project/deploy/smart/","title":"smart","text":""},{"location":"hardis/project/deploy/smart/#hardisprojectdeploysmart","title":"hardis:project:deploy:smart","text":""},{"location":"hardis/project/deploy/smart/#description","title":"Description","text":"

Smart deploy of SFDX sources to target org, with many useful options.

In case of errors, tips to fix them will be included within the error messages.

"},{"location":"hardis/project/deploy/smart/#quick-deploy","title":"Quick Deploy","text":"

In case Pull Request comments are configured on the project, Quick Deploy will try to be used (equivalent to button Quick Deploy)

If you do not want to use QuickDeploy, define variable SFDX_HARDIS_QUICK_DEPLOY=false

  • GitHub Pull Requests comments config
  • Gitlab Merge requests notes config
  • Azure Pull Requests comments config
"},{"location":"hardis/project/deploy/smart/#delta-deployments","title":"Delta deployments","text":"

To activate delta deployments, define property useDeltaDeployment: true in config/.sfdx-hardis.yml.

This will activate delta deployments only between minor and major branches (major to major remains full deployment mode)

If you want to force the delta deployment into major orgs (ex: preprod to prod), this is not recommended but you can use env variable ALWAYS_ENABLE_DELTA_DEPLOYMENT=true

"},{"location":"hardis/project/deploy/smart/#smart-deployments-tests","title":"Smart Deployments Tests","text":"

Not all metadata updates can break test classes, use Smart Deployment Tests to skip running test classes if ALL the following conditions are met:

  • Delta deployment is activated and applicable to the source and target branches
  • Delta deployed metadatas are all matching the list of NOT_IMPACTING_METADATA_TYPES (see below)
  • Target org is not a production org

Activate Smart Deployment tests with:

  • env variable USE_SMART_DEPLOYMENT_TESTS=true
  • .sfdx-hardis.yml config property useSmartDeploymentTests: true

Defaut list for NOT_IMPACTING_METADATA_TYPES (can be overridden with comma-separated list on env var NOT_IMPACTING_METADATA_TYPES)

  • Audience
  • AuraDefinitionBundle
  • Bot
  • BotVersion
  • ContentAsset
  • CustomObjectTranslation
  • CustomSite
  • CustomTab
  • Dashboard
  • ExperienceBundle
  • Flexipage
  • GlobalValueSetTranslation
  • Layout
  • LightningComponentBundle
  • NavigationMenu
  • ReportType
  • Report
  • SiteDotCom
  • StandardValueSetTranslation
  • StaticResource
  • Translations

Note: if you want to disable Smart test classes for a PR, add nosmart in the text of the latest commit.

"},{"location":"hardis/project/deploy/smart/#dynamic-deployment-items-overwrite-management","title":"Dynamic deployment items / Overwrite management","text":"

If necessary,you can define the following files (that supports wildcards *):

  • manifest/package-no-overwrite.xml: Every element defined in this file will be deployed only if it is not existing yet in the target org (can be useful with ListView for example, if the client wants to update them directly in production org).
    • Can be overridden for a branch using .sfdx-hardis.yml property packageNoOverwritePath or environment variable PACKAGE_NO_OVERWRITE_PATH (for example, define: packageNoOverwritePath: manifest/package-no-overwrite-main.xml in config file config/.sfdx-hardis.main.yml)
  • manifest/packageXmlOnChange.xml: Every element defined in this file will not be deployed if it already has a similar definition in target org (can be useful for SharingRules for example)

See Overwrite management documentation

"},{"location":"hardis/project/deploy/smart/#deployment-plan","title":"Deployment plan","text":"

If you need to deploy in multiple steps, you can define a property deploymentPlan in .sfdx-hardis.yml.

  • If a file manifest/package.xml is found, it will be placed with order 0 in the deployment plan
  • If a file manifest/destructiveChanges.xml is found, it will be executed as --postdestructivechanges
  • If env var SFDX_HARDIS_DEPLOY_IGNORE_SPLIT_PACKAGES is defined as false , split of package.xml will be applied

Example:

deploymentPlan:\n  packages:\n    - label: Deploy Flow-Workflow\n      packageXmlFile: manifest/splits/packageXmlFlowWorkflow.xml\n      order: 6\n    - label: Deploy SharingRules - Case\n      packageXmlFile: manifest/splits/packageXmlSharingRulesCase.xml\n      order: 30\n      waitAfter: 30\n
"},{"location":"hardis/project/deploy/smart/#packages-installation","title":"Packages installation","text":"

You can define a list of package to install during deployments using property installedPackages

  • If INSTALL_PACKAGES_DURING_CHECK_DEPLOY is defined as true (or installPackagesDuringCheckDeploy: true in .sfdx-hardis.yml), packages will be installed even if the command is called with --check mode
  • You can automatically update this property by listing all packages installed on an org using command sf hardis:org:retrieve:packageconfig

Example:

installedPackages:\n  - Id: 0A35r0000009EtECAU\n    SubscriberPackageId: 033i0000000LVMYAA4\n    SubscriberPackageName: Marketing Cloud\n    SubscriberPackageNamespace: et4ae5\n    SubscriberPackageVersionId: 04t6S000000l11iQAA\n    SubscriberPackageVersionName: Marketing Cloud\n    SubscriberPackageVersionNumber: 236.0.0.2\n    installOnScratchOrgs: true                  // true or false depending you want to install this package when creating a new scratch org\n    installDuringDeployments: true              // set as true to install package during a deployment using sf hardis:project:deploy:smart\n    installationkey: xxxxxxxxxxxxxxxxxxxx       // if the package has a password, write it in this property\n    - Id: 0A35r0000009F9CCAU\n    SubscriberPackageId: 033b0000000Pf2AAAS\n    SubscriberPackageName: Declarative Lookup Rollup Summaries Tool\n    SubscriberPackageNamespace: dlrs\n    SubscriberPackageVersionId: 04t5p000001BmLvAAK\n    SubscriberPackageVersionName: Release\n    SubscriberPackageVersionNumber: 2.15.0.9\n    installOnScratchOrgs: true\n    installDuringDeployments: true\n
"},{"location":"hardis/project/deploy/smart/#deployment-pre-or-post-commands","title":"Deployment pre or post commands","text":"

You can define command lines to run before or after a deployment, with parameters:

  • id: Unique Id for the command
  • label: Human readable label for the command
  • skipIfError: If defined to \"true\", the post-command won't be run if there is a deployment failure
  • context: Defines the context where the command will be run. Can be all (default), check-deployment-only or process-deployment-only
  • runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)

If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

Example:

commandsPreDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='deploy.github@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n\ncommandsPostDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to desired username\n    command: sf data update record --sobject User --where \"Username='admin-yser@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n  - id: someActionToRunJustOneTime\n    label: And to run only if deployment is success\n    command: sf sfdmu:run ...\n    skipIfError: true\n    context: process-deployment-only\n    runOnlyOnceByOrg: true\n
"},{"location":"hardis/project/deploy/smart/#automated-fixes-post-deployments","title":"Automated fixes post deployments","text":""},{"location":"hardis/project/deploy/smart/#list-view-with-scope-mine","title":"List view with scope Mine","text":"

If you defined a property listViewsToSetToMine in your .sfdx-hardis.yml, related ListViews will be set to Mine ( see command https://sfdx-hardis.cloudity.com/hardis/org/fix/listviewmine/ )

Example:

listViewsToSetToMine:\n  - \"Operation__c:MyCurrentOperations\"\n  - \"Operation__c:MyFinalizedOperations\"\n  - \"Opportunity:Default_Opportunity_Pipeline\"\n  - \"Opportunity:MyCurrentSubscriptions\"\n  - \"Opportunity:MySubscriptions\"\n  - \"Account:MyActivePartners\"\n

Troubleshooting: if you need to fix ListViews with mine from an alpine-linux based docker image, use this workaround in your dockerfile:

# Do not use puppeteer embedded chromium\nRUN apk add --update --no-cache chromium\nENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=\"true\"\nENV CHROMIUM_PATH=\"/usr/bin/chromium-browser\"\nENV PUPPETEER_EXECUTABLE_PATH=\"$\\{CHROMIUM_PATH}\" // remove \\ before {\n

If you need to increase the deployment waiting time (sf project deploy start --wait arg), you can define env variable SFDX_DEPLOY_WAIT_MINUTES (default: 120)

If you need notifications to be sent using the current Pull Request and not the one just merged (see use case), define env variable SFDX_HARDIS_DEPLOY_BEFORE_MERGE=true

If you want to disable the calculation and display of Flow Visual Git Diff in Pull Request comments, define variable SFDX_DISABLE_FLOW_DIFF=true

"},{"location":"hardis/project/deploy/smart/#parameters","title":"Parameters","text":"Name Type Description Default Required Options check-c boolean Only checks the deployment, there is no impact on target org debug-d boolean Activate debug mode (more logs) delta boolean Applies sfdx-git-delta to package.xml before other deployment processes flags-dir option undefined json boolean Format output as json. packagexml-p option Path to package.xml containing what you want to deploy in target org runtests-r option If testlevel=RunSpecifiedTests, please provide a list of classes. If testlevel=RunRepositoryTests, can contain a regular expression to keep only class names matching it. If not set, will run all test classes found in the repo. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined testlevel-l option Level of tests to validate deployment. RunRepositoryTests auto-detect and run all repository test classes NoTestRunRunSpecifiedTestsRunRepositoryTestsRunRepositoryTestsExceptSeeAllDataRunLocalTestsRunAllTestsInOrg websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/deploy/smart/#examples","title":"Examples","text":"
$ sf hardis:project:deploy:smart\n
$ sf hardis:project:deploy:smart --check\n
$ sf hardis:project:deploy:smart --check --testlevel RunRepositoryTests\n
$ sf hardis:project:deploy:smart --check --testlevel RunRepositoryTests --runtests '^(?!FLI|MyPrefix).*'\n
$ sf hardis:project:deploy:smart --check --testlevel RunRepositoryTestsExceptSeeAllData\n
$ sf hardis:project:deploy:smart\n
$ FORCE_TARGET_BRANCH=preprod NODE_OPTIONS=--inspect-brk sf hardis:project:deploy:smart --check --websocket localhost:2702 --skipauth --target-org nicolas.vuillamy@myclient.com.preprod\n
$ SYSTEM_ACCESSTOKEN=xxxxxx SYSTEM_COLLECTIONURI=https://dev.azure.com/xxxxxxx/ SYSTEM_TEAMPROJECT=\"xxxxxxx\" BUILD_REPOSITORY_ID=xxxxx SYSTEM_PULLREQUEST_PULLREQUESTID=1418 FORCE_TARGET_BRANCH=uat NODE_OPTIONS=--inspect-brk sf hardis:project:deploy:smart --check --websocket localhost:2702 --skipauth --target-org my.salesforce@org.com\n
$ CI_SFDX_HARDIS_BITBUCKET_TOKEN=xxxxxx BITBUCKET_WORKSPACE=sfdxhardis-demo BITBUCKET_REPO_SLUG=test BITBUCKET_BUILD_NUMBER=1 BITBUCKET_BRANCH=uat BITBUCKET_PR_ID=2 FORCE_TARGET_BRANCH=uat NODE_OPTIONS=--inspect-brk sf hardis:project:deploy:smart --check --websocket localhost:2702 --skipauth --target-org my-salesforce-org@client.com\n
$ GITHUB_TOKEN=xxxx GITHUB_REPOSITORY=my-user/my-repo FORCE_TARGET_BRANCH=uat NODE_OPTIONS=--inspect-brk sf hardis:project:deploy:smart --check --websocket localhost:2702 --skipauth --target-org my-salesforce-org@client.com\n
"},{"location":"hardis/project/deploy/start/","title":"start","text":""},{"location":"hardis/project/deploy/start/#hardisprojectdeploystart","title":"hardis:project:deploy:start","text":""},{"location":"hardis/project/deploy/start/#description","title":"Description","text":"

sfdx-hardis wrapper for sf project deploy start that displays tips to solve deployment errors.

Note: Use --json argument to have better results

See documentation of Salesforce command

"},{"location":"hardis/project/deploy/start/#deployment-pre-or-post-commands","title":"Deployment pre or post commands","text":"

You can define command lines to run before or after a deployment, with parameters:

  • id: Unique Id for the command
  • label: Human readable label for the command
  • skipIfError: If defined to \"true\", the post-command won't be run if there is a deployment failure
  • context: Defines the context where the command will be run. Can be all (default), check-deployment-only or process-deployment-only
  • runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)

If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

Example:

commandsPreDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='deploy.github@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n\ncommandsPostDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to desired username\n    command: sf data update record --sobject User --where \"Username='admin-yser@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n  - id: someActionToRunJustOneTime\n    label: And to run only if deployment is success\n    command: sf sfdmu:run ...\n    skipIfError: true\n    context: process-deployment-only\n    runOnlyOnceByOrg: true\n
"},{"location":"hardis/project/deploy/start/#parameters","title":"Parameters","text":"Name Type Description Default Required Options api-version-a option api-version async boolean async coverage-formatters option coverage-formatters debug boolean debug dry-run boolean dry-run flags-dir option undefined ignore-conflicts-c boolean ignore-conflicts ignore-errors-r boolean ignore-errors ignore-warnings-g boolean ignore-warnings json boolean Format output as json. junit boolean junit manifest-x option manifest metadata-m option metadata metadata-dir option metadata-dir post-destructive-changes option post-destructive-changes pre-destructive-changes option pre-destructive-changes purge-on-delete boolean purge-on-delete results-dir option results-dir single-package boolean single-package source-dir-d option source-dir target-org-o option undefined test-level option test-level tests option tests wait-w option wait 33"},{"location":"hardis/project/deploy/start/#examples","title":"Examples","text":""},{"location":"hardis/project/deploy/validate/","title":"validate","text":""},{"location":"hardis/project/deploy/validate/#hardisprojectdeployvalidate","title":"hardis:project:deploy:validate","text":""},{"location":"hardis/project/deploy/validate/#description","title":"Description","text":"

sfdx-hardis wrapper for sf project deploy validate that displays tips to solve deployment errors.

Note: Use --json argument to have better results

See documentation of Salesforce command

"},{"location":"hardis/project/deploy/validate/#deployment-pre-or-post-commands","title":"Deployment pre or post commands","text":"

You can define command lines to run before or after a deployment, with parameters:

  • id: Unique Id for the command
  • label: Human readable label for the command
  • skipIfError: If defined to \"true\", the post-command won't be run if there is a deployment failure
  • context: Defines the context where the command will be run. Can be all (default), check-deployment-only or process-deployment-only
  • runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)

If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

Example:

commandsPreDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='deploy.github@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n\ncommandsPostDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to desired username\n    command: sf data update record --sobject User --where \"Username='admin-yser@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n  - id: someActionToRunJustOneTime\n    label: And to run only if deployment is success\n    command: sf sfdmu:run ...\n    skipIfError: true\n    context: process-deployment-only\n    runOnlyOnceByOrg: true\n
"},{"location":"hardis/project/deploy/validate/#parameters","title":"Parameters","text":"Name Type Description Default Required Options api-version-a option api-version async boolean async coverage-formatters option coverage-formatters debug boolean debug dry-run boolean dry-run flags-dir option undefined ignore-conflicts-c boolean ignore-conflicts ignore-errors-r boolean ignore-errors ignore-warnings-g boolean ignore-warnings json boolean Format output as json. junit boolean junit manifest-x option manifest metadata-m option metadata metadata-dir option metadata-dir post-destructive-changes option post-destructive-changes pre-destructive-changes option pre-destructive-changes purge-on-delete boolean purge-on-delete results-dir option results-dir single-package boolean single-package source-dir-d option source-dir target-org-o option undefined test-level option test-level tests option tests wait-w option wait 33"},{"location":"hardis/project/deploy/validate/#examples","title":"Examples","text":""},{"location":"hardis/project/deploy/sources/dx/","title":"dx","text":""},{"location":"hardis/project/deploy/sources/dx/#hardisprojectdeploysourcesdx","title":"hardis:project:deploy:sources:dx","text":""},{"location":"hardis/project/deploy/sources/dx/#description","title":"Description","text":"

Smart deploy of SFDX sources to target org, with many useful options.

In case of errors, tips to fix them will be included within the error messages.

"},{"location":"hardis/project/deploy/sources/dx/#quick-deploy","title":"Quick Deploy","text":"

In case Pull Request comments are configured on the project, Quick Deploy will try to be used (equivalent to button Quick Deploy)

If you do not want to use QuickDeploy, define variable SFDX_HARDIS_QUICK_DEPLOY=false

  • GitHub Pull Requests comments config
  • Gitlab Merge requests notes config
  • Azure Pull Requests comments config
"},{"location":"hardis/project/deploy/sources/dx/#delta-deployments","title":"Delta deployments","text":"

To activate delta deployments, define property useDeltaDeployment: true in config/.sfdx-hardis.yml.

This will activate delta deployments only between minor and major branches (major to major remains full deployment mode)

If you want to force the delta deployment into major orgs (ex: preprod to prod), this is not recommended but you can use env variable ALWAYS_ENABLE_DELTA_DEPLOYMENT=true

"},{"location":"hardis/project/deploy/sources/dx/#smart-deployments-tests","title":"Smart Deployments Tests","text":"

Not all metadata updates can break test classes, use Smart Deployment Tests to skip running test classes if ALL the following conditions are met:

  • Delta deployment is activated and applicable to the source and target branches
  • Delta deployed metadatas are all matching the list of NOT_IMPACTING_METADATA_TYPES (see below)
  • Target org is not a production org

Activate Smart Deployment tests with:

  • env variable USE_SMART_DEPLOYMENT_TESTS=true
  • .sfdx-hardis.yml config property useSmartDeploymentTests: true

Defaut list for NOT_IMPACTING_METADATA_TYPES (can be overridden with comma-separated list on env var NOT_IMPACTING_METADATA_TYPES)

  • Audience
  • AuraDefinitionBundle
  • Bot
  • BotVersion
  • ContentAsset
  • CustomObjectTranslation
  • CustomSite
  • CustomTab
  • Dashboard
  • ExperienceBundle
  • Flexipage
  • GlobalValueSetTranslation
  • Layout
  • LightningComponentBundle
  • NavigationMenu
  • ReportType
  • Report
  • SiteDotCom
  • StandardValueSetTranslation
  • StaticResource
  • Translations

Note: if you want to disable Smart test classes for a PR, add nosmart in the text of the latest commit.

"},{"location":"hardis/project/deploy/sources/dx/#dynamic-deployment-items-overwrite-management","title":"Dynamic deployment items / Overwrite management","text":"

If necessary,you can define the following files (that supports wildcards *):

  • manifest/package-no-overwrite.xml: Every element defined in this file will be deployed only if it is not existing yet in the target org (can be useful with ListView for example, if the client wants to update them directly in production org).
    • Can be overridden for a branch using .sfdx-hardis.yml property packageNoOverwritePath or environment variable PACKAGE_NO_OVERWRITE_PATH (for example, define: packageNoOverwritePath: manifest/package-no-overwrite-main.xml in config file config/.sfdx-hardis.main.yml)
  • manifest/packageXmlOnChange.xml: Every element defined in this file will not be deployed if it already has a similar definition in target org (can be useful for SharingRules for example)

See Overwrite management documentation

"},{"location":"hardis/project/deploy/sources/dx/#deployment-plan","title":"Deployment plan","text":"

If you need to deploy in multiple steps, you can define a property deploymentPlan in .sfdx-hardis.yml.

  • If a file manifest/package.xml is found, it will be placed with order 0 in the deployment plan
  • If a file manifest/destructiveChanges.xml is found, it will be executed as --postdestructivechanges
  • If env var SFDX_HARDIS_DEPLOY_IGNORE_SPLIT_PACKAGES is defined as false , split of package.xml will be applied

Example:

deploymentPlan:\n  packages:\n    - label: Deploy Flow-Workflow\n      packageXmlFile: manifest/splits/packageXmlFlowWorkflow.xml\n      order: 6\n    - label: Deploy SharingRules - Case\n      packageXmlFile: manifest/splits/packageXmlSharingRulesCase.xml\n      order: 30\n      waitAfter: 30\n
"},{"location":"hardis/project/deploy/sources/dx/#packages-installation","title":"Packages installation","text":"

You can define a list of package to install during deployments using property installedPackages

  • If INSTALL_PACKAGES_DURING_CHECK_DEPLOY is defined as true (or installPackagesDuringCheckDeploy: true in .sfdx-hardis.yml), packages will be installed even if the command is called with --check mode
  • You can automatically update this property by listing all packages installed on an org using command sf hardis:org:retrieve:packageconfig

Example:

installedPackages:\n  - Id: 0A35r0000009EtECAU\n    SubscriberPackageId: 033i0000000LVMYAA4\n    SubscriberPackageName: Marketing Cloud\n    SubscriberPackageNamespace: et4ae5\n    SubscriberPackageVersionId: 04t6S000000l11iQAA\n    SubscriberPackageVersionName: Marketing Cloud\n    SubscriberPackageVersionNumber: 236.0.0.2\n    installOnScratchOrgs: true                  // true or false depending you want to install this package when creating a new scratch org\n    installDuringDeployments: true              // set as true to install package during a deployment using sf hardis:project:deploy:smart\n    installationkey: xxxxxxxxxxxxxxxxxxxx       // if the package has a password, write it in this property\n    - Id: 0A35r0000009F9CCAU\n    SubscriberPackageId: 033b0000000Pf2AAAS\n    SubscriberPackageName: Declarative Lookup Rollup Summaries Tool\n    SubscriberPackageNamespace: dlrs\n    SubscriberPackageVersionId: 04t5p000001BmLvAAK\n    SubscriberPackageVersionName: Release\n    SubscriberPackageVersionNumber: 2.15.0.9\n    installOnScratchOrgs: true\n    installDuringDeployments: true\n
"},{"location":"hardis/project/deploy/sources/dx/#deployment-pre-or-post-commands","title":"Deployment pre or post commands","text":"

You can define command lines to run before or after a deployment, with parameters:

  • id: Unique Id for the command
  • label: Human readable label for the command
  • skipIfError: If defined to \"true\", the post-command won't be run if there is a deployment failure
  • context: Defines the context where the command will be run. Can be all (default), check-deployment-only or process-deployment-only
  • runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)

If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

Example:

commandsPreDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='deploy.github@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n\ncommandsPostDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to desired username\n    command: sf data update record --sobject User --where \"Username='admin-yser@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n  - id: someActionToRunJustOneTime\n    label: And to run only if deployment is success\n    command: sf sfdmu:run ...\n    skipIfError: true\n    context: process-deployment-only\n    runOnlyOnceByOrg: true\n
"},{"location":"hardis/project/deploy/sources/dx/#automated-fixes-post-deployments","title":"Automated fixes post deployments","text":""},{"location":"hardis/project/deploy/sources/dx/#list-view-with-scope-mine","title":"List view with scope Mine","text":"

If you defined a property listViewsToSetToMine in your .sfdx-hardis.yml, related ListViews will be set to Mine ( see command https://sfdx-hardis.cloudity.com/hardis/org/fix/listviewmine/ )

Example:

listViewsToSetToMine:\n  - \"Operation__c:MyCurrentOperations\"\n  - \"Operation__c:MyFinalizedOperations\"\n  - \"Opportunity:Default_Opportunity_Pipeline\"\n  - \"Opportunity:MyCurrentSubscriptions\"\n  - \"Opportunity:MySubscriptions\"\n  - \"Account:MyActivePartners\"\n

Troubleshooting: if you need to fix ListViews with mine from an alpine-linux based docker image, use this workaround in your dockerfile:

# Do not use puppeteer embedded chromium\nRUN apk add --update --no-cache chromium\nENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=\"true\"\nENV CHROMIUM_PATH=\"/usr/bin/chromium-browser\"\nENV PUPPETEER_EXECUTABLE_PATH=\"$\\{CHROMIUM_PATH}\" // remove \\ before {\n

If you need to increase the deployment waiting time (sf project deploy start --wait arg), you can define env variable SFDX_DEPLOY_WAIT_MINUTES (default: 120)

If you need notifications to be sent using the current Pull Request and not the one just merged (see use case), define env variable SFDX_HARDIS_DEPLOY_BEFORE_MERGE=true

If you want to disable the calculation and display of Flow Visual Git Diff in Pull Request comments, define variable SFDX_DISABLE_FLOW_DIFF=true

"},{"location":"hardis/project/deploy/sources/dx/#parameters","title":"Parameters","text":"Name Type Description Default Required Options check-c boolean Only checks the deployment, there is no impact on target org debug-d boolean Activate debug mode (more logs) delta boolean Applies sfdx-git-delta to package.xml before other deployment processes flags-dir option undefined json boolean Format output as json. packagexml-p option Path to package.xml containing what you want to deploy in target org runtests-r option If testlevel=RunSpecifiedTests, please provide a list of classes. If testlevel=RunRepositoryTests, can contain a regular expression to keep only class names matching it. If not set, will run all test classes found in the repo. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined testlevel-l option Level of tests to validate deployment. RunRepositoryTests auto-detect and run all repository test classes NoTestRunRunSpecifiedTestsRunRepositoryTestsRunRepositoryTestsExceptSeeAllDataRunLocalTestsRunAllTestsInOrg websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/deploy/sources/dx/#examples","title":"Examples","text":"
$ sf hardis:project:deploy:smart\n
$ sf hardis:project:deploy:smart --check\n
$ sf hardis:project:deploy:smart --check --testlevel RunRepositoryTests\n
$ sf hardis:project:deploy:smart --check --testlevel RunRepositoryTests --runtests '^(?!FLI|MyPrefix).*'\n
$ sf hardis:project:deploy:smart --check --testlevel RunRepositoryTestsExceptSeeAllData\n
$ sf hardis:project:deploy:smart\n
$ FORCE_TARGET_BRANCH=preprod NODE_OPTIONS=--inspect-brk sf hardis:project:deploy:smart --check --websocket localhost:2702 --skipauth --target-org nicolas.vuillamy@myclient.com.preprod\n
$ SYSTEM_ACCESSTOKEN=xxxxxx SYSTEM_COLLECTIONURI=https://dev.azure.com/xxxxxxx/ SYSTEM_TEAMPROJECT=\"xxxxxxx\" BUILD_REPOSITORY_ID=xxxxx SYSTEM_PULLREQUEST_PULLREQUESTID=1418 FORCE_TARGET_BRANCH=uat NODE_OPTIONS=--inspect-brk sf hardis:project:deploy:smart --check --websocket localhost:2702 --skipauth --target-org my.salesforce@org.com\n
$ CI_SFDX_HARDIS_BITBUCKET_TOKEN=xxxxxx BITBUCKET_WORKSPACE=sfdxhardis-demo BITBUCKET_REPO_SLUG=test BITBUCKET_BUILD_NUMBER=1 BITBUCKET_BRANCH=uat BITBUCKET_PR_ID=2 FORCE_TARGET_BRANCH=uat NODE_OPTIONS=--inspect-brk sf hardis:project:deploy:smart --check --websocket localhost:2702 --skipauth --target-org my-salesforce-org@client.com\n
$ GITHUB_TOKEN=xxxx GITHUB_REPOSITORY=my-user/my-repo FORCE_TARGET_BRANCH=uat NODE_OPTIONS=--inspect-brk sf hardis:project:deploy:smart --check --websocket localhost:2702 --skipauth --target-org my-salesforce-org@client.com\n
"},{"location":"hardis/project/deploy/sources/metadata/","title":"metadata","text":""},{"location":"hardis/project/deploy/sources/metadata/#hardisprojectdeploysourcesmetadata","title":"hardis:project:deploy:sources:metadata","text":""},{"location":"hardis/project/deploy/sources/metadata/#description","title":"Description","text":"

Deploy metadatas to source org

"},{"location":"hardis/project/deploy/sources/metadata/#parameters","title":"Parameters","text":"Name Type Description Default Required Options check-c boolean Only checks the deployment, there is no impact on target org debug-d boolean Activate debug mode (more logs) deploydir-x option Deploy directory . destructivepackagexml-k option Path to destructiveChanges.xml file to deploy filter-f boolean Filter metadatas before deploying flags-dir option undefined json boolean Format output as json. packagexml-p option Path to package.xml file to deploy skipauth boolean Skip authentication check when a default username is required target-org-o option undefined testlevel-l option Level of tests to apply to validate deployment RunLocalTests NoTestRunRunSpecifiedTestsRunLocalTestsRunAllTestsInOrg websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/deploy/sources/metadata/#examples","title":"Examples","text":"
$ sf hardis:project:deploy:sources:metadata\n
"},{"location":"hardis/project/fix/profiletabs/","title":"profiletabs","text":""},{"location":"hardis/project/fix/profiletabs/#hardisprojectfixprofiletabs","title":"hardis:project:fix:profiletabs","text":""},{"location":"hardis/project/fix/profiletabs/#description","title":"Description","text":"

Interactive prompts to add tab visibilities that are not retrieved by project retrieve start

"},{"location":"hardis/project/fix/profiletabs/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. path-p option Root folder /home/runner/work/sfdx-hardis/sfdx-hardis skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/fix/profiletabs/#examples","title":"Examples","text":"
$ sf hardis:project:fix:profiletabs\n
"},{"location":"hardis/project/fix/v53flexipages/","title":"v53flexipages","text":""},{"location":"hardis/project/fix/v53flexipages/#hardisprojectfixv53flexipages","title":"hardis:project:fix:v53flexipages","text":""},{"location":"hardis/project/fix/v53flexipages/#description","title":"Description","text":"

Fix flexipages for apiVersion v53 (Winter22).

Note: Update api version to 53.0 in package.xml and sfdx-project.json

"},{"location":"hardis/project/fix/v53flexipages/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. path-p option Root folder /home/runner/work/sfdx-hardis/sfdx-hardis skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/fix/v53flexipages/#examples","title":"Examples","text":"
$ sf hardis:project:fix:v53flexipages\n
"},{"location":"hardis/project/generate/flow-git-diff/","title":"flow-git-diff","text":""},{"location":"hardis/project/generate/flow-git-diff/#hardisprojectgenerateflow-git-diff","title":"hardis:project:generate:flow-git-diff","text":""},{"location":"hardis/project/generate/flow-git-diff/#description","title":"Description","text":"

Generate Flow Visual Git Diff markdown between 2 commits

This command requires @mermaid-js/mermaid-cli to be installed.

Run npm install @mermaid-js/mermaid-cli --global

"},{"location":"hardis/project/generate/flow-git-diff/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined flow option Path to flow file (will be prompted if not set) json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/generate/flow-git-diff/#examples","title":"Examples","text":"
$ sf hardis:project:generate:flow-git-diff\n
"},{"location":"hardis/project/generate/gitdelta/","title":"gitdelta","text":""},{"location":"hardis/project/generate/gitdelta/#hardisprojectgenerategitdelta","title":"hardis:project:generate:gitdelta","text":""},{"location":"hardis/project/generate/gitdelta/#description","title":"Description","text":"

Generate package.xml git delta between 2 commits

"},{"location":"hardis/project/generate/gitdelta/#parameters","title":"Parameters","text":"Name Type Description Default Required Options branch option Git branch to use to generate delta debug-d boolean Activate debug mode (more logs) flags-dir option undefined fromcommit option Hash of commit to start from json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required tocommit option Hash of commit to stop at websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/generate/gitdelta/#examples","title":"Examples","text":"
$ sf hardis:project:generate:gitdelta\n
"},{"location":"hardis/project/metadata/findduplicates/","title":"findduplicates","text":""},{"location":"hardis/project/metadata/findduplicates/#hardisprojectmetadatafindduplicates","title":"hardis:project:metadata:findduplicates","text":""},{"location":"hardis/project/metadata/findduplicates/#description","title":"Description","text":"

find duplicate values in XML file(s). Find duplicate values in XML file(s). Keys to be checked can be configured in config/sfdx-hardis.yml using property metadataDuplicateFindKeys.

Default config : metadataDuplicateFindKeys : [object Object]

"},{"location":"hardis/project/metadata/findduplicates/#parameters","title":"Parameters","text":"Name Type Description Default Required Options files-f option XML metadata files path flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/project/metadata/findduplicates/#examples","title":"Examples","text":"
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Layout xmlns=\"http://soap.sforce.com/2006/04/metadata\">\n  <layoutSections>\n      ...\n      <layoutColumns>\n          <layoutItems>\n              <behavior>Required</behavior>\n              <field>Name</field>\n          </layoutItems>\n          <layoutItems>\n              <behavior>Required</behavior>\n              <field>Name</field>\n          </layoutItems>\n      </layoutColumns>\n    </layoutSections>\n</Layout>\n
$ sf hardis:project:metadata:findduplicates --file layout.layout-meta.xml\n[sfdx-hardis] Duplicate values in layout.layout-meta.xml\n  - Key    : Layout.layoutSections.layoutColumns.layoutItems.field\n  - Values : Name\n
$ sf hardis:project.metadata:findduplicates -f \"force-app/main/default/**/*.xml\"\n[sfdx-hardis] hardis:project:metadata:findduplicates execution time 0:00:00.397\n[sfdx-hardis] Duplicate values in layout1.layout-meta.xml\n  - Key    : Layout.layoutSections.layoutColumns.layoutItems.field\n  - Values : CreatedById\n\n[sfdx-hardis] Duplicate values in layout2.layout-meta.xml\n  - Key    : Layout.layoutSections.layoutColumns.layoutItems.field\n  - Values : LastModifiedById, Name\n
"},{"location":"hardis/scratch/create/","title":"create","text":""},{"location":"hardis/scratch/create/#hardisscratchcreate","title":"hardis:scratch:create","text":""},{"location":"hardis/scratch/create/#description","title":"Description","text":"

Create and initialize a scratch org or a source-tracked sandbox (config can be defined using config/.sfdx-hardis.yml):

  • Install packages
    • Use property installedPackages
  • Push sources
  • Assign permission sets
    • Use property initPermissionSets
  • Run apex initialization scripts
    • Use property scratchOrgInitApexScripts
  • Load data
    • Use property dataPackages
"},{"location":"hardis/scratch/create/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined forcenew-n boolean If an existing scratch org exists, do not reuse it but create a new one json boolean Format output as json. pool boolean Creates the scratch org for a scratch org pool skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/scratch/create/#examples","title":"Examples","text":"
$ sf hardis:scratch:create\n
"},{"location":"hardis/scratch/delete/","title":"delete","text":""},{"location":"hardis/scratch/delete/#hardisscratchdelete","title":"hardis:scratch:delete","text":""},{"location":"hardis/scratch/delete/#description","title":"Description","text":"

Assisted menu to delete scratch orgs associated to a DevHub

"},{"location":"hardis/scratch/delete/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/scratch/delete/#examples","title":"Examples","text":"
$ sf hardis:scratch:delete\n
"},{"location":"hardis/scratch/pull/","title":"pull","text":""},{"location":"hardis/scratch/pull/#hardisscratchpull","title":"hardis:scratch:pull","text":""},{"location":"hardis/scratch/pull/#description","title":"Description","text":"

This commands pulls the updates you performed in your scratch or sandbox org, into your local files

Then, you probably want to stage and commit the files containing the updates you want to keep, as explained in this video.

  • Calls sf project retrieve start under the hood
  • If there are errors, proposes to automatically add erroneous item in .forceignore, then pull again
  • If you don't see your updated items in the results, you can manually retrieve using SF Extension Org Browser or Salesforce CLI
  • If you want to always retrieve sources like CustomApplication that are not always detected as updates by project:retrieve:start , you can define property autoRetrieveWhenPull in .sfdx-hardis.yml

Example:

autoRetrieveWhenPull:\n  - CustomApplication:MyCustomApplication\n  - CustomApplication:MyOtherCustomApplication\n  - CustomApplication:MyThirdCustomApp\n

"},{"location":"hardis/scratch/pull/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/scratch/pull/#examples","title":"Examples","text":"
$ sf hardis:scratch:pull\n
"},{"location":"hardis/scratch/push/","title":"push","text":""},{"location":"hardis/scratch/push/#hardisscratchpush","title":"hardis:scratch:push","text":""},{"location":"hardis/scratch/push/#description","title":"Description","text":"

Push local files to scratch org

Calls sf project deploy start under the hood

"},{"location":"hardis/scratch/push/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/scratch/push/#examples","title":"Examples","text":"
$ sf hardis:scratch:push\n
"},{"location":"hardis/scratch/pool/create/","title":"create","text":""},{"location":"hardis/scratch/pool/create/#hardisscratchpoolcreate","title":"hardis:scratch:pool:create","text":""},{"location":"hardis/scratch/pool/create/#description","title":"Description","text":"

Select a data storage service and configure information to build a scratch org pool

Run the command, follow instruction, then you need to schedule a daily CI job for the pool maintenance:

- Define CI ENV variable SCRATCH_ORG_POOL with value \"true\"

- Call the following lines in the CI job:

  sf hardis:auth:login --devhub\n  sf hardis:scratch:pool:refresh\n
"},{"location":"hardis/scratch/pool/create/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/scratch/pool/create/#examples","title":"Examples","text":"
$ sf hardis:scratch:pool:configure\n
"},{"location":"hardis/scratch/pool/localauth/","title":"localauth","text":""},{"location":"hardis/scratch/pool/localauth/#hardisscratchpoollocalauth","title":"hardis:scratch:pool:localauth","text":""},{"location":"hardis/scratch/pool/localauth/#description","title":"Description","text":"

Calls the related storage service to request api keys and secrets that allows a local user to fetch a scratch org from scratch org pool

"},{"location":"hardis/scratch/pool/localauth/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/scratch/pool/localauth/#examples","title":"Examples","text":"
$ sf hardis:scratch:pool:localauth\n
"},{"location":"hardis/scratch/pool/refresh/","title":"refresh","text":""},{"location":"hardis/scratch/pool/refresh/#hardisscratchpoolrefresh","title":"hardis:scratch:pool:refresh","text":""},{"location":"hardis/scratch/pool/refresh/#description","title":"Description","text":"

Create enough scratch orgs to fill the pool

"},{"location":"hardis/scratch/pool/refresh/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/scratch/pool/refresh/#examples","title":"Examples","text":"
$ sf hardis:scratch:pool:refresh\n
"},{"location":"hardis/scratch/pool/reset/","title":"reset","text":""},{"location":"hardis/scratch/pool/reset/#hardisscratchpoolreset","title":"hardis:scratch:pool:reset","text":""},{"location":"hardis/scratch/pool/reset/#description","title":"Description","text":"

Reset scratch org pool (delete all scratches in the pool)

"},{"location":"hardis/scratch/pool/reset/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/scratch/pool/reset/#examples","title":"Examples","text":"
$ sf hardis:scratch:pool:refresh\n
"},{"location":"hardis/scratch/pool/view/","title":"view","text":""},{"location":"hardis/scratch/pool/view/#hardisscratchpoolview","title":"hardis:scratch:pool:view","text":""},{"location":"hardis/scratch/pool/view/#description","title":"Description","text":"

Displays all stored content of project scratch org pool if defined

"},{"location":"hardis/scratch/pool/view/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/scratch/pool/view/#examples","title":"Examples","text":"
$ sf hardis:scratch:pool:view\n
"},{"location":"hardis/source/deploy/","title":"deploy","text":""},{"location":"hardis/source/deploy/#hardissourcedeploy","title":"hardis:source:deploy","text":""},{"location":"hardis/source/deploy/#description","title":"Description","text":"

sfdx-hardis wrapper for sfdx force:source:deploy that displays tips to solve deployment errors.

Additional to the base command wrapper: If using --checkonly, add options --checkcoverage and --coverageformatters json-summary to check that org coverage is > 75% (or value defined in .sfdx-hardis.yml property apexTestsMinCoverageOrgWide)

"},{"location":"hardis/source/deploy/#deployment-results","title":"Deployment results","text":"

You can also have deployment results as pull request comments, on:

  • GitHub (see GitHub Pull Requests comments config)
  • Gitlab (see Gitlab integration configuration)
  • Azure DevOps (see Azure integration configuration)

"},{"location":"hardis/source/deploy/#deployment-pre-or-post-commands","title":"Deployment pre or post commands","text":"

You can define command lines to run before or after a deployment, with parameters:

  • id: Unique Id for the command
  • label: Human readable label for the command
  • skipIfError: If defined to \"true\", the post-command won't be run if there is a deployment failure
  • context: Defines the context where the command will be run. Can be all (default), check-deployment-only or process-deployment-only
  • runOnlyOnceByOrg: If set to true, the command will be run only one time per org. A record of SfdxHardisTrace__c is stored to make that possible (it needs to be existing in target org)

If the commands are not the same depending on the target org, you can define them into config/branches/.sfdx-hardis-BRANCHNAME.yml instead of root config/.sfdx-hardis.yml

Example:

commandsPreDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to the deployment user\n    command: sf data update record --sobject User --where \"Username='deploy.github@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n\ncommandsPostDeploy:\n  - id: knowledgeUnassign\n    label: Remove KnowledgeUser right to the user who has it\n    command: sf data update record --sobject User --where \"UserPermissionsKnowledgeUser='true'\" --values \"UserPermissionsKnowledgeUser='false'\" --json\n  - id: knowledgeAssign\n    label: Assign Knowledge user to desired username\n    command: sf data update record --sobject User --where \"Username='admin-yser@myclient.com'\" --values \"UserPermissionsKnowledgeUser='true'\" --json\n  - id: someActionToRunJustOneTime\n    label: And to run only if deployment is success\n    command: sf sfdmu:run ...\n    skipIfError: true\n    context: process-deployment-only\n    runOnlyOnceByOrg: true\n

Notes:

  • You can disable coloring of errors in red by defining env variable SFDX_HARDIS_DEPLOY_ERR_COLORS=false

See documentation of Salesforce command

"},{"location":"hardis/source/deploy/#parameters","title":"Parameters","text":"Name Type Description Default Required Options checkcoverage boolean Check Apex org coverage checkonly-c boolean checkonly coverageformatters option coverageformatters debug boolean debug flags-dir option undefined forceoverwrite-f boolean forceoverwrite ignoreerrors boolean ignoreErrors ignorewarnings-g boolean ignoreWarnings json boolean Format output as json. junit boolean junit manifest-x option flagsLong.manifest metadata-m option metadata postdestructivechanges option postdestructivechanges predestructivechanges option predestructivechanges resultsdir option resultsdir runtests-r option runTests soapdeploy boolean soapDeploy sourcepath-p option sourcePath target-org-o option undefined testlevel-l option testlevel NoTestRun NoTestRunRunSpecifiedTestsRunLocalTestsRunAllTestsInOrg tracksource-t boolean tracksource validateddeployrequestid-q option validateDeployRequestId verbose boolean verbose wait-w option wait 60 websocket option websocket"},{"location":"hardis/source/deploy/#examples","title":"Examples","text":"
$ sf hardis:source:deploy -x manifest/package.xml --wait 60 --ignorewarnings --testlevel RunLocalTests --postdestructivechanges ./manifest/destructiveChanges.xml --target-org nicolas.vuillamy@cloudity.com.sfdxhardis --checkonly --checkcoverage --verbose --coverageformatters json-summary\n
"},{"location":"hardis/source/push/","title":"push","text":""},{"location":"hardis/source/push/#hardissourcepush","title":"hardis:source:push","text":""},{"location":"hardis/source/push/#description","title":"Description","text":"

sfdx-hardis wrapper for sfdx force:source:push that displays tips to solve deployment errors.

See documentation of Salesforce command

"},{"location":"hardis/source/push/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug boolean debug flags-dir option undefined forceoverwrite-f boolean forceoverwrite ignorewarnings-g boolean ignorewarnings json boolean Format output as json. quiet boolean quiet target-org-o option undefined wait-w option wait 60 websocket option websocket"},{"location":"hardis/source/push/#examples","title":"Examples","text":""},{"location":"hardis/source/retrieve/","title":"retrieve","text":""},{"location":"hardis/source/retrieve/#hardissourceretrieve","title":"hardis:source:retrieve","text":""},{"location":"hardis/source/retrieve/#description","title":"Description","text":"

sfdx-hardis wrapper for sfdx force:source:retrieve

  • If no retrieve constraint is sent, as assisted menu will request the list of metadatas to retrieve
  • If no org is selected , an assisted menu will request the user to choose one

See documentation of Salesforce command

"},{"location":"hardis/source/retrieve/#parameters","title":"Parameters","text":"Name Type Description Default Required Options apiversion-a option Override the api version used for api requests made by this command debug-d boolean debugMode flags-dir option undefined forceoverwrite-f boolean forceoverwrite json boolean Format output as json. manifest-x option manifest metadata-m option metadata packagenames-n option packagenames skipauth boolean Skip authentication check when a default username is required sourcepath-p option sourcePath target-org-o option undefined tracksource-t boolean tracksource verbose boolean verbose wait-w option wait websocket option websocket"},{"location":"hardis/source/retrieve/#examples","title":"Examples","text":""},{"location":"hardis/work/new/","title":"new","text":""},{"location":"hardis/work/new/#hardisworknew","title":"hardis:work:new","text":""},{"location":"hardis/work/new/#description","title":"Description","text":"

Assisted menu to start working on a Salesforce task.

Advanced instructions in Create New Task documentation

At the end of the command, it will allow you to work on either a scratch org or a sandbox, depending on your choices.

Under the hood, it can:

  • Make git pull to be up to date with target branch
  • Create new git branch with formatted name (you can override the choices using .sfdx-hardis.yml property branchPrefixChoices)
  • Create and initialize a scratch org or a source-tracked sandbox (config can be defined using config/.sfdx-hardis.yml):
  • (and for scratch org only for now):
    • Install packages - Use property installedPackages
      • Push sources
      • Assign permission sets
        • Use property initPermissionSets
      • Run apex initialization scripts
        • Use property scratchOrgInitApexScripts
      • Load data
        • Use property dataPackages
"},{"location":"hardis/work/new/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-dev-hub-v option undefined target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/work/new/#examples","title":"Examples","text":"
$ sf hardis:work:task:new\n
"},{"location":"hardis/work/refresh/","title":"refresh","text":""},{"location":"hardis/work/refresh/#hardisworkrefresh","title":"hardis:work:refresh","text":""},{"location":"hardis/work/refresh/#description","title":"Description","text":"

Make my local branch and my scratch org up to date with the most recent sources

"},{"location":"hardis/work/refresh/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. nopull-n boolean No scratch pull before save (careful if you use that!) skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/work/refresh/#examples","title":"Examples","text":"
$ sf hardis:work:refresh\n
"},{"location":"hardis/work/resetselection/","title":"resetselection","text":""},{"location":"hardis/work/resetselection/#hardisworkresetselection","title":"hardis:work:resetselection","text":""},{"location":"hardis/work/resetselection/#description","title":"Description","text":"

Resets the selection that we want to add in the merge request

Calls a soft git reset behind the hood

"},{"location":"hardis/work/resetselection/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required target-org-o option undefined websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/work/resetselection/#examples","title":"Examples","text":"
$ sf hardis:work:resetsave\n
"},{"location":"hardis/work/save/","title":"save","text":""},{"location":"hardis/work/save/#hardisworksave","title":"hardis:work:save","text":""},{"location":"hardis/work/save/#description","title":"Description","text":"

When a work task is completed, guide user to create a merge request

Advanced instructions in Publish a task

  • Generate package-xml diff using sfdx-git-delta
  • Automatically update manifest/package.xml and manifest/destructiveChanges.xml according to the committed updates
  • Automatically Clean XML files using .sfdx-hardis.yml properties
    • autocleantypes: List of auto-performed sources cleanings, available on command hardis:project:clean:references
    • autoRemoveUserPermissions: List of userPermission to automatically remove from profile metadatas

Example:

autoCleanTypes:\n  - checkPermissions\n  - destructivechanges\n  - datadotcom\n  - minimizeProfiles\n  - listViewsMine\nautoRemoveUserPermissions:\n  - EnableCommunityAppLauncher\n  - FieldServiceAccess\n  - OmnichannelInventorySync\n  - SendExternalEmailAvailable\n  - UseOmnichannelInventoryAPIs\n  - ViewDataLeakageEvents\n  - ViewMLModels\n  - ViewPlatformEvents\n  - WorkCalibrationUser\n
  • Push commit to server
"},{"location":"hardis/work/save/#parameters","title":"Parameters","text":"Name Type Description Default Required Options auto boolean No user prompts (when called from CI for example) debug-d boolean Activate debug mode (more logs) flags-dir option undefined json boolean Format output as json. noclean-c boolean No cleaning of local sources nogit-g boolean No automated git operations nopull-n boolean No scratch pull before save skipauth boolean Skip authentication check when a default username is required target-org-o option undefined targetbranch option Name of the Merge Request target branch. Will be guessed or prompted if not provided. websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/work/save/#examples","title":"Examples","text":"
$ sf hardis:work:task:save\n
$ sf hardis:work:task:save --nopull --nogit --noclean\n
"},{"location":"hardis/work/ws/","title":"ws","text":""},{"location":"hardis/work/ws/#hardisworkws","title":"hardis:work:ws","text":""},{"location":"hardis/work/ws/#description","title":"Description","text":"

Technical calls to WebSocket functions

"},{"location":"hardis/work/ws/#parameters","title":"Parameters","text":"Name Type Description Default Required Options debug-d boolean Activate debug mode (more logs) event-e option WebSocket event flags-dir option undefined json boolean Format output as json. skipauth boolean Skip authentication check when a default username is required websocket option Websocket host:port for VsCode SFDX Hardis UI integration"},{"location":"hardis/work/ws/#examples","title":"Examples","text":"
$ sf hardis:work:ws --event refreshStatus\n
"},{"location":"hello/world/","title":"world","text":""},{"location":"hello/world/#helloworld","title":"hello:world","text":""},{"location":"hello/world/#description","title":"Description","text":"

Say hello either to the world or someone you know.

"},{"location":"hello/world/#parameters","title":"Parameters","text":"Name Type Description Default Required Options flags-dir option undefined json boolean Format output as json. name-n option This person can be anyone in the world! World"},{"location":"hello/world/#examples","title":"Examples","text":"
Say hello to the world:\n<%= config.bin %> <%= command.id %>\n
Say hello to someone you know:\n<%= config.bin %> <%= command.id %> --name Astro\n
"},{"location":"sf-deployment-assistant/A-sharing-rule-may-be-useless/","title":"A sharing rule may be useless (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/A-sharing-rule-may-be-useless/#a-sharing-rule-may-be-useless","title":"A sharing rule may be useless","text":""},{"location":"sf-deployment-assistant/A-sharing-rule-may-be-useless/#detection","title":"Detection","text":"
  • String: Required field is missing: sharingCriteriaRules
"},{"location":"sf-deployment-assistant/A-sharing-rule-may-be-useless/#resolution","title":"Resolution","text":"
Are you sure you need this sharing rule ? You may remove it from the sfdx project\n
"},{"location":"sf-deployment-assistant/API-Version-error/","title":"API Version error (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/API-Version-error/#api-version-error","title":"API Version error","text":""},{"location":"sf-deployment-assistant/API-Version-error/#detection","title":"Detection","text":"
  • RegExp: Error (.*) The (.*) apiVersion can't be \"([0-9]+)\"
"},{"location":"sf-deployment-assistant/API-Version-error/#resolution","title":"Resolution","text":"
{1} metadata has probably been created/updated in a sandbox already upgraded to next platform version (ex: Sandbox in Summer'23 and Production in Spring'23)\n- First, try to update the api version in the XML of {1} metadata file (decrement the number in <apiVersion>{3}.0</apiVersion>)\n- If it still doesn't work because the metadata structure has changed between version, you may try a sf project:retrieve:start of the metadata by forcing --api-version at the end of the command.\n
"},{"location":"sf-deployment-assistant/Allow-deployment-with-pending-Apex-Jobs/","title":"Allow deployment with pending Apex Jobs (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Allow-deployment-with-pending-Apex-Jobs/#allow-deployment-with-pending-apex-jobs","title":"Allow deployment with pending Apex Jobs","text":""},{"location":"sf-deployment-assistant/Allow-deployment-with-pending-Apex-Jobs/#detection","title":"Detection","text":"
  • String: You can bypass this error by allowing deployments with Apex jobs in the Deployment Settings page in Setup.
"},{"location":"sf-deployment-assistant/Allow-deployment-with-pending-Apex-Jobs/#resolution","title":"Resolution","text":"
Go to target org, in Setup -> Deployment Settings -> Activate option \"Allow deployments of components when corresponding Apex jobs are pending or in progress.\"\n
"},{"location":"sf-deployment-assistant/Async-exception-in-test-class/","title":"Async exception in test class (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Async-exception-in-test-class/#async-exception-in-test-class","title":"Async exception in test class","text":""},{"location":"sf-deployment-assistant/Async-exception-in-test-class/#detection","title":"Detection","text":"
  • RegExp: System.AsyncException: (.*) Apex
"},{"location":"sf-deployment-assistant/Async-exception-in-test-class/#resolution","title":"Resolution","text":"
This may be a test class implementation issue in {1}.\nPlease check https://developer.salesforce.com/forums/?id=9060G0000005kVLQAY\n
"},{"location":"sf-deployment-assistant/CRM-Analytics--A-Recipe-must-specify-a-DataFlow/","title":"CRM Analytics: A Recipe must specify a DataFlow (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/CRM-Analytics--A-Recipe-must-specify-a-DataFlow/#crm-analytics-a-recipe-must-specify-a-dataflow","title":"CRM Analytics: A Recipe must specify a DataFlow","text":""},{"location":"sf-deployment-assistant/CRM-Analytics--A-Recipe-must-specify-a-DataFlow/#detection","title":"Detection","text":"
  • RegExp: Error (.*) A Recipe must specify a Dataflow
"},{"location":"sf-deployment-assistant/CRM-Analytics--A-Recipe-must-specify-a-DataFlow/#resolution","title":"Resolution","text":"
You must include related WaveDataFlow {1} in sources (and probably in package.xml too).\nTo retrieve it, run: sf project retrieve start -m WaveDataFlow:{1} -u SOURCE_ORG_USERNAME\nYou can also retrieve all analytics sources in one shot using sf hardis:org:retrieve:source:analytics -u SOURCE_ORG_USERNAME\n  - https://salesforce.stackexchange.com/a/365453/33522\n  - https://help.salesforce.com/s/articleView?id=000319274&type=1\n
"},{"location":"sf-deployment-assistant/Campaign-can-not-be-updated/","title":"Campaign can not be updated","text":"

title: \"Campaign can not be updated (Deployment assistant)\" description: \"How to solve Salesforce deployment error \\\"The object \"Campaign\" can't be updated\\\"\"

"},{"location":"sf-deployment-assistant/Campaign-can-not-be-updated/#campaign-can-not-be-updated","title":"Campaign can not be updated","text":""},{"location":"sf-deployment-assistant/Campaign-can-not-be-updated/#detection","title":"Detection","text":"
  • String: The object \"Campaign\" can't be updated
"},{"location":"sf-deployment-assistant/Campaign-can-not-be-updated/#resolution","title":"Resolution","text":"
Add \"MarketingUser\" in project-scratch-def.json features\nIf it is already done, you may manually check \"MarketingUser\" field on the scratch org user\n
"},{"location":"sf-deployment-assistant/Can-not-change-field-type-to-a-formula-field/","title":"Can not change field type to a formula field (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Can-not-change-field-type-to-a-formula-field/#can-not-change-field-type-to-a-formula-field","title":"Can not change field type to a formula field","text":""},{"location":"sf-deployment-assistant/Can-not-change-field-type-to-a-formula-field/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Cannot update a field from a Formula to something else
"},{"location":"sf-deployment-assistant/Can-not-change-field-type-to-a-formula-field/#resolution","title":"Resolution","text":"
You need to manually delete or rename the field in the target org to allow the deployment to pass\n- First, try to manually delete field {1} in the target org\n- if you can't delete {1}, rename it into {1}_ToDel, then once the deployment done, delete {1}_ToDel\n
"},{"location":"sf-deployment-assistant/Can-not-change-field-type-with-picklist/","title":"Can not change field type with picklist (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Can-not-change-field-type-with-picklist/#can-not-change-field-type-with-picklist","title":"Can not change field type with picklist","text":""},{"location":"sf-deployment-assistant/Can-not-change-field-type-with-picklist/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Cannot change which global value set this picklist uses
"},{"location":"sf-deployment-assistant/Can-not-change-field-type-with-picklist/#resolution","title":"Resolution","text":"
You probably updated the type of field {1}, and Salesforce does not allows that with deployments. You can:\n- Try to manually change the type of {1} directly in target org, but it may not be technically possible\n- Delete field {1} in target org: it will be recreated after deployment (but you will loose data on existing records, so be careful if your target is a production org)\n- Create another field with desired type and manage data recovery if the target is a production org\n
"},{"location":"sf-deployment-assistant/Can-not-change-type-due-to-existing-data/","title":"Can not change type due to existing data (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Can-not-change-type-due-to-existing-data/#can-not-change-type-due-to-existing-data","title":"Can not change type due to existing data","text":""},{"location":"sf-deployment-assistant/Can-not-change-type-due-to-existing-data/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Cannot change type due to existing data
"},{"location":"sf-deployment-assistant/Can-not-change-type-due-to-existing-data/#resolution","title":"Resolution","text":"
It is usually not recommended to change types of fields, but if it's really necessary you can:\n- Manually change the type of {1} in the target org\n- If you can't manually change the type:\n  - you may modify the dependencies (Formulas, Flows...) using {1}, so they don't use this field\n  - you can also delete dependencies (Formulas, Flows...) using {1}, but make sure they are deployed again later\n- More help: https://help.salesforce.com/s/articleView?id=000327186&type=1\n
"},{"location":"sf-deployment-assistant/Can-not-delete-custom-field/","title":"Can not delete custom field (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Can-not-delete-custom-field/#can-not-delete-custom-field","title":"Can not delete custom field","text":""},{"location":"sf-deployment-assistant/Can-not-delete-custom-field/#detection","title":"Detection","text":"
  • RegExp: This (.*) is referenced elsewhere in salesforce.com
  • RegExp: Le champ personnalis\u00e9 (.*) est utilis\u00e9 dans (.*)
"},{"location":"sf-deployment-assistant/Can-not-delete-custom-field/#resolution","title":"Resolution","text":"
Custom field {1} can not be deleted because it is used elsewhere. Remove its references ans try again\nTHIS MAY BE A FALSE POSITIVE if you are just testing the deployment, as destructiveChanges are deployed separately from updated items deployment check\n
"},{"location":"sf-deployment-assistant/Can-not-delete-record-type/","title":"Can not delete record type (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Can-not-delete-record-type/#can-not-delete-record-type","title":"Can not delete record type","text":""},{"location":"sf-deployment-assistant/Can-not-delete-record-type/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Cannot delete record type through API
"},{"location":"sf-deployment-assistant/Can-not-delete-record-type/#resolution","title":"Resolution","text":"
You need to manually delete record type {1} in target org\n- Edit record type {1}, uncheck \"Active\"\n- Delete record type {1}\n
"},{"location":"sf-deployment-assistant/Can-not-find-folder/","title":"Can not find folder (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Can-not-find-folder/#can-not-find-folder","title":"Can not find folder","text":""},{"location":"sf-deployment-assistant/Can-not-find-folder/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Cannot find folder:(.*)
"},{"location":"sf-deployment-assistant/Can-not-find-folder/#resolution","title":"Resolution","text":"
Folder {2} is missing.\n- If folder {2} is existing in sources, add it in related package.xml\n- If folder {2} is not existing in DX sources, please use sf hardis:project:clean:retrievefolders to retrieve it\n- If both previous solutions did not work, go create manually folder {2} in target org\n
"},{"location":"sf-deployment-assistant/Can-not-find-user--2-/","title":"Can not find user (2) (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Can-not-find-user--2-/#can-not-find-user-2","title":"Can not find user (2)","text":""},{"location":"sf-deployment-assistant/Can-not-find-user--2-/#detection","title":"Detection","text":"
  • RegExp: Error (.*) In field: (.*) - no User named (.*) found
"},{"location":"sf-deployment-assistant/Can-not-find-user--2-/#resolution","title":"Resolution","text":"
You made reference to username {3} in {1}, and it probably does not exist in the target org.\n- Do not use named users, but user public groups for assignments -> https://help.salesforce.com/s/articleView?id=sf.creating_and_editing_groups.htm&type=5\n- or Create matching user {3} in the target deployment org\n- or open {1} metadata and remove the XML part referring to hardcoded username {3}\n
"},{"location":"sf-deployment-assistant/Can-not-find-user/","title":"Can not find user (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Can-not-find-user/#can-not-find-user","title":"Can not find user","text":""},{"location":"sf-deployment-assistant/Can-not-find-user/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Cannot find a user that matches any of the following usernames
"},{"location":"sf-deployment-assistant/Can-not-find-user/#resolution","title":"Resolution","text":"
You made reference to username(s) in {1}, and those users probably do not exist in target org.\n- Do not use named users, but user public groups for assignments -> https://help.salesforce.com/s/articleView?id=sf.creating_and_editing_groups.htm&type=5\n- or Create matching user(s) in the target deployment org\n- or Remove the XML part referring to hardcoded usernames\n\nExample of XML you have to remove in {1}:\n\n<folderShares>\n  <accessLevel>Manage</accessLevel>\n  <sharedTo>nicolas.vuillamy@hardis-scratch-po-tgci-root-develop_20220412_0604.com</sharedTo>\n  <sharedToType>User</sharedToType>\n</folderShares>\n
"},{"location":"sf-deployment-assistant/Can-not-test-item-deployment-in-simulation-mode/","title":"Can not test item deployment in simulation mode (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Can-not-test-item-deployment-in-simulation-mode/#can-not-test-item-deployment-in-simulation-mode","title":"Can not test item deployment in simulation mode","text":""},{"location":"sf-deployment-assistant/Can-not-test-item-deployment-in-simulation-mode/#detection","title":"Detection","text":"
  • RegExp: Test only deployment cannot update
"},{"location":"sf-deployment-assistant/Can-not-test-item-deployment-in-simulation-mode/#resolution","title":"Resolution","text":"
THIS IS A FALSE POSITIVE\nWhen effective deployment will happen, it should pass\n
"},{"location":"sf-deployment-assistant/Cannot-update-a-field-to-a-Summary-from-something-else/","title":"Cannot update a field to a Summary from something else (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Cannot-update-a-field-to-a-Summary-from-something-else/#cannot-update-a-field-to-a-summary-from-something-else","title":"Cannot update a field to a Summary from something else","text":""},{"location":"sf-deployment-assistant/Cannot-update-a-field-to-a-Summary-from-something-else/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Cannot update a field to a (.*) from something else
"},{"location":"sf-deployment-assistant/Cannot-update-a-field-to-a-Summary-from-something-else/#resolution","title":"Resolution","text":"
You probably updated the type of field {1} to type {2}, and Salesforce does not allows that with deployments. You can:\n- Try to manually change the type of {1} directly in target org, but it may not be technically possible\n- Delete field {1} in target org: it will be recreated after deployment (but you will loose data on existing records, so be careful if your target is a production org)\n- Create another field with desired type and manage data recovery if the target is a production org\n
"},{"location":"sf-deployment-assistant/Change-Matching-Rule/","title":"Change Matching Rule (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Change-Matching-Rule/#change-matching-rule","title":"Change Matching Rule","text":""},{"location":"sf-deployment-assistant/Change-Matching-Rule/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Before you change a matching rule, you must deactivate it
"},{"location":"sf-deployment-assistant/Change-Matching-Rule/#resolution","title":"Resolution","text":"
To be able to deploy, you must go in target org setup to manually deactivate matching rule {1}\n
"},{"location":"sf-deployment-assistant/Condition-missing-reference/","title":"Condition missing reference","text":"

title: \"Condition missing reference (Deployment assistant)\" description: \"How to solve Salesforce deployment error \\\"Error (.) field integrity exception: unknown (A condition has a reference to (.), which doesn't exist.)\\\"\"

"},{"location":"sf-deployment-assistant/Condition-missing-reference/#condition-missing-reference","title":"Condition missing reference","text":""},{"location":"sf-deployment-assistant/Condition-missing-reference/#detection","title":"Detection","text":"
  • RegExp: Error (.*) field integrity exception: unknown \\(A condition has a reference to (.*), which doesn't exist.\\)
"},{"location":"sf-deployment-assistant/Condition-missing-reference/#resolution","title":"Resolution","text":"
There is a reference to {2} in {1}, and {2} is not found. You can either:\n- Add {2} in your deployment sources and make sure it is named in package.xml\n- Remove the reference to {2} in {1}\n
"},{"location":"sf-deployment-assistant/Couldn-t-retrieve-or-load-information-on-the-field/","title":"Couldn t retrieve or load information on the field","text":"

title: \"Couldn't retrieve or load information on the field (Deployment assistant)\" description: \"How to solve Salesforce deployment error \\\"Error (.) Something went wrong. We couldn't retrieve or load the information on the field: (.).\\\"\"

"},{"location":"sf-deployment-assistant/Couldn-t-retrieve-or-load-information-on-the-field/#couldnt-retrieve-or-load-information-on-the-field","title":"Couldn't retrieve or load information on the field","text":""},{"location":"sf-deployment-assistant/Couldn-t-retrieve-or-load-information-on-the-field/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Something went wrong. We couldn't retrieve or load the information on the field: (.*)\\.
"},{"location":"sf-deployment-assistant/Couldn-t-retrieve-or-load-information-on-the-field/#resolution","title":"Resolution","text":"
There is a reference to {2} in {1}, and {2} is not found. You can either:\n- Commit {2} in your deployment sources and make sure it is named in package.xml\n- Remove the reference to {2} in {1}\n
"},{"location":"sf-deployment-assistant/Custom-field-not-found/","title":"Custom field not found (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Custom-field-not-found/#custom-field-not-found","title":"Custom field not found","text":""},{"location":"sf-deployment-assistant/Custom-field-not-found/#detection","title":"Detection","text":"
  • RegExp: Error (.*) In field: (.*) - no CustomField named (.*)\\.(.*) found
"},{"location":"sf-deployment-assistant/Custom-field-not-found/#examples","title":"Examples","text":"
  • Error PS_Admin In field: field - no CustomField named User.expcloud__Portal_Username__c found
"},{"location":"sf-deployment-assistant/Custom-field-not-found/#resolution","title":"Resolution","text":"
A reference to a custom field {3}.{4} is not found in {1}:\n- If you renamed {3}.{4}, do a search/replace in {1} with previous field name and {4}\n- If you deleted {3}.{4}, or if you don't want to deploy it, do a search on {4} in all sources, and remove all XML elements referring to {3}.{4} (except in destructiveChanges.xml)\n- If {3}.{4} should exist, make sure it is in force-app/main/default/objects/{3}/fields and that {3}.{4} is in manifest/package.xml in CustomField section\n- If {3}.{4} is standard, the error is because {3}.{4} is not available in the org you are trying to deploy to. You can:\n  - Remove the reference to {4} in the XML of {1} ( maybe sf hardis:project:clean:references can clean automatically for you ! )\n  - Activate the required features/license in the target org\n
"},{"location":"sf-deployment-assistant/Custom-metadata-entry-not-found/","title":"Custom metadata entry not found (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Custom-metadata-entry-not-found/#custom-metadata-entry-not-found","title":"Custom metadata entry not found","text":""},{"location":"sf-deployment-assistant/Custom-metadata-entry-not-found/#detection","title":"Detection","text":"
  • RegExp: Error (.*) In field: (.*) - no CustomMetadata named (.*) found
"},{"location":"sf-deployment-assistant/Custom-metadata-entry-not-found/#resolution","title":"Resolution","text":"
A reference to a custom metadata {3} of type {2} is not found in {1}:\n- Are you sure you deployed {3} ?\n- If you use a package.xml, is {3} present within type CustomMetadata ?\n
"},{"location":"sf-deployment-assistant/Custom-object-not-found/","title":"Custom object not found (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Custom-object-not-found/#custom-object-not-found","title":"Custom object not found","text":""},{"location":"sf-deployment-assistant/Custom-object-not-found/#detection","title":"Detection","text":"
  • RegExp: Error (.*) In field: field - no CustomObject named (.*) found
"},{"location":"sf-deployment-assistant/Custom-object-not-found/#resolution","title":"Resolution","text":"
A reference to a custom object {2} is not found in {1}:\n- If you renamed the custom object, do a search/replace in sources with previous object name and new object name\n- If you deleted the custom object, or if you don't want to deploy it, do a search on the custom object name, and remove XML elements referencing it\n- If the object should exist, make sure it is in force-app/main/default/objects and that the object name is in manifest/package.xml in CustomObject section\nYou may also have a look to command sf hardis:project:clean:references\n
"},{"location":"sf-deployment-assistant/Dependent-class-is-invalid-and-needs-recompilation/","title":"Dependent class is invalid and needs recompilation (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Dependent-class-is-invalid-and-needs-recompilation/#dependent-class-is-invalid-and-needs-recompilation","title":"Dependent class is invalid and needs recompilation","text":""},{"location":"sf-deployment-assistant/Dependent-class-is-invalid-and-needs-recompilation/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Dependent class is invalid and needs recompilation
"},{"location":"sf-deployment-assistant/Dependent-class-is-invalid-and-needs-recompilation/#resolution","title":"Resolution","text":"
Solve the other errors and this one will disappear !\n
"},{"location":"sf-deployment-assistant/Duplicate-label/","title":"Duplicate label (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Duplicate-label/#duplicate-label","title":"Duplicate label","text":""},{"location":"sf-deployment-assistant/Duplicate-label/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Duplicate label: (.*)
"},{"location":"sf-deployment-assistant/Duplicate-label/#resolution","title":"Resolution","text":"
You probably renamed the picklist API name for {2}. Please update manually the picklist {1} in the target org to avoid to have a duplicate label\n
"},{"location":"sf-deployment-assistant/Duplicate-value-Platform-Action-Id-List/","title":"Duplicate value Platform Action Id List (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Duplicate-value-Platform-Action-Id-List/#duplicate-value-platform-action-id-list","title":"Duplicate value Platform Action Id List","text":""},{"location":"sf-deployment-assistant/Duplicate-value-Platform-Action-Id-List/#detection","title":"Detection","text":"
  • String: duplicate value found: PlatformActionListId duplicates value on record with id
"},{"location":"sf-deployment-assistant/Duplicate-value-Platform-Action-Id-List/#resolution","title":"Resolution","text":"
There are probably issue with conflict management. Open the XML of the source item, and replace all <sortOrder> numbers to make an ascending order, starting with 0\n
"},{"location":"sf-deployment-assistant/Empty-source-items/","title":"Empty source items (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Empty-source-items/#empty-source-items","title":"Empty source items","text":""},{"location":"sf-deployment-assistant/Empty-source-items/#detection","title":"Detection","text":"
  • String: Required field is missing: sharingOwnerRules
  • String: Required field is missing: standardValue
  • String: Required field is missing: valueTranslation
"},{"location":"sf-deployment-assistant/Empty-source-items/#resolution","title":"Resolution","text":"
You probably retrieved empty items, that must not be included within the SFDX project\nTo remove them, please run sfdx:hardis:project:clean:emptyitems\n
"},{"location":"sf-deployment-assistant/Enable-CRM-Analytics/","title":"Enable CRM Analytics (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Enable-CRM-Analytics/#enable-crm-analytics","title":"Enable CRM Analytics","text":""},{"location":"sf-deployment-assistant/Enable-CRM-Analytics/#detection","title":"Detection","text":"
  • String: It should be created by enabling the CRM Analytics Cloud preference
"},{"location":"sf-deployment-assistant/Enable-CRM-Analytics/#resolution","title":"Resolution","text":"
You must enable CRM Analytics (ex Wave, Einstein Analytics & Tableau CRM) in the target org.\nYou probably also need to add CRM Analytics Admin Permission Set assignment to the deployment user\n
"},{"location":"sf-deployment-assistant/Error-parsing-file/","title":"Error parsing file (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Error-parsing-file/#error-parsing-file","title":"Error parsing file","text":""},{"location":"sf-deployment-assistant/Error-parsing-file/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Error parsing file: (.*)
"},{"location":"sf-deployment-assistant/Error-parsing-file/#resolution","title":"Resolution","text":"
There has been an error parsing the XML file of {1}: {2}\n- Open file {1} and look where the error can be ! (merge issue, typo, XML tag not closed...)\n
"},{"location":"sf-deployment-assistant/Expired-Access---Refresh-Token/","title":"Expired Access / Refresh Token (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Expired-Access---Refresh-Token/#expired-access-refresh-token","title":"Expired Access / Refresh Token","text":""},{"location":"sf-deployment-assistant/Expired-Access---Refresh-Token/#detection","title":"Detection","text":"
  • String: expired access/refresh token
"},{"location":"sf-deployment-assistant/Expired-Access---Refresh-Token/#resolution","title":"Resolution","text":"
Run command \"Select another org\" from Status panel (or sf hardis:org:select) to authenticate again to your org\n
"},{"location":"sf-deployment-assistant/Field-not-available-for-element/","title":"Field not available for element (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Field-not-available-for-element/#field-not-available-for-element","title":"Field not available for element","text":""},{"location":"sf-deployment-assistant/Field-not-available-for-element/#detection","title":"Detection","text":"
  • RegExp: Field (.*) is not available for
"},{"location":"sf-deployment-assistant/Field-not-available-for-element/#resolution","title":"Resolution","text":"
You probably changed the type of field {1}.\nFind field {1} in the source XML, and remove the section using it\n
"},{"location":"sf-deployment-assistant/Flow-must-be-deleted-manually/","title":"Flow must be deleted manually (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Flow-must-be-deleted-manually/#flow-must-be-deleted-manually","title":"Flow must be deleted manually","text":""},{"location":"sf-deployment-assistant/Flow-must-be-deleted-manually/#detection","title":"Detection","text":"
  • RegExp: .flow (.*) insufficient access rights on cross-reference id
"},{"location":"sf-deployment-assistant/Flow-must-be-deleted-manually/#resolution","title":"Resolution","text":"
Flow {1} can not be deleted using deployments, please delete it manually in the target org using menu Setup -> Flows , context menu on {1} -> View details and versions -> Deactivate all versions -> Delete flow\n
"},{"location":"sf-deployment-assistant/Formula-picklist-field-issue/","title":"Formula picklist field issue (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Formula-picklist-field-issue/#formula-picklist-field-issue","title":"Formula picklist field issue","text":""},{"location":"sf-deployment-assistant/Formula-picklist-field-issue/#detection","title":"Detection","text":"
  • String: Les champs de liste de s\u00e9lection sont pris en charge uniquement dans certaines fonctions.
"},{"location":"sf-deployment-assistant/Formula-picklist-field-issue/#resolution","title":"Resolution","text":"
You probably changed the type of a field that is used in a formula.\nUpdate the formula to use a field compliant with formulas.\nMore details at https://help.salesforce.com/articleView?id=sf.tips_on_building_formulas.htm&type=5\n
"},{"location":"sf-deployment-assistant/Insufficient-access-rights-on-cross-reference-id/","title":"Insufficient access rights on cross-reference id (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Insufficient-access-rights-on-cross-reference-id/#insufficient-access-rights-on-cross-reference-id","title":"Insufficient access rights on cross-reference id","text":""},{"location":"sf-deployment-assistant/Insufficient-access-rights-on-cross-reference-id/#detection","title":"Detection","text":"
  • RegExp: Error (.*) insufficient access rights on cross-reference id
"},{"location":"sf-deployment-assistant/Insufficient-access-rights-on-cross-reference-id/#resolution","title":"Resolution","text":"
- If {1} is a Flow, it can not be deleted using deployments, please delete it manually in the target org using menu Setup -> Flows , context menu on {1} -> View details and versions -> Deactivate all versions -> Delete flow\n- If you changed a custom field from unique to not unique, you need to manually make the change in the target org\n
"},{"location":"sf-deployment-assistant/Invalid-field-for-upsert/","title":"Invalid field for upsert","text":"

title: \"Invalid field for upsert (Deployment assistant)\" description: \"How to solve Salesforce deployment error \\\"Error (.) Invalid field for upsert, must be an External Id custom or standard indexed field: (.) ((.*))\\\"\"

"},{"location":"sf-deployment-assistant/Invalid-field-for-upsert/#invalid-field-for-upsert","title":"Invalid field for upsert","text":""},{"location":"sf-deployment-assistant/Invalid-field-for-upsert/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Invalid field for upsert, must be an External Id custom or standard indexed field: (.*) \\((.*)\\)
"},{"location":"sf-deployment-assistant/Invalid-field-for-upsert/#resolution","title":"Resolution","text":"
You tried to use field {2} for an upsert call in {1}.\n- Is it declared as externalId ?\n- Is the customIndex source file present in the deployment ?\n- If it is declared as externalId and customIndex is present, you may have to go manually define the field as externalId in the target org\n
"},{"location":"sf-deployment-assistant/Invalid-field-in-related-list/","title":"Invalid field in related list (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Invalid-field-in-related-list/#invalid-field-in-related-list","title":"Invalid field in related list","text":""},{"location":"sf-deployment-assistant/Invalid-field-in-related-list/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Invalid field:(.*) in related list:(.*)
"},{"location":"sf-deployment-assistant/Invalid-field-in-related-list/#resolution","title":"Resolution","text":"
Field {2} is unknown. You can:\n- Activate the related feature license or option to make {2} existing in target org\n- Update XML of {1} to remove reference to field {2} in the related list {3}\n- Update XML of {1} to remove the whole related list {3}\nExample of XML to remove:\n<relatedLists>\n  <fields>SOLUTION.ISSUE</fields>\n  <fields>SOLUTION.SOLUTION_NUMBER</fields>\n  <fields>SOLUTION.STATUS</fields>\n  <fields>CORE.USERS.ALIAS</fields>\n  <relatedList>RelatedSolutionList</relatedList>\n</relatedLists>\n
"},{"location":"sf-deployment-assistant/Invalid-formula-grouping-context/","title":"Invalid formula grouping context (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Invalid-formula-grouping-context/#invalid-formula-grouping-context","title":"Invalid formula grouping context","text":""},{"location":"sf-deployment-assistant/Invalid-formula-grouping-context/#detection","title":"Detection","text":"
  • String: Invalid custom summary formula definition: You must select a grouping context to use any report summary function
"},{"location":"sf-deployment-assistant/Invalid-formula-grouping-context/#resolution","title":"Resolution","text":"
You need to update your Report definition. See workaround here -> https://salesforce.stackexchange.com/questions/294850/grouping-error-with-prevgroupval-function\n
"},{"location":"sf-deployment-assistant/Invalid-report-type/","title":"Invalid report type (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Invalid-report-type/#invalid-report-type","title":"Invalid report type","text":""},{"location":"sf-deployment-assistant/Invalid-report-type/#detection","title":"Detection","text":"
  • RegExp: Error (.*) invalid report type
"},{"location":"sf-deployment-assistant/Invalid-report-type/#resolution","title":"Resolution","text":"
Report type is missing for report {1}\n- Open report {1} to se what report type is used\n- Retrieve the report type from an org and add it to the sfdx sources\n
"},{"location":"sf-deployment-assistant/Invalid-scope-Mine--not-allowed/","title":"Invalid scope:Mine, not allowed (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Invalid-scope-Mine--not-allowed/#invalid-scopemine-not-allowed","title":"Invalid scope:Mine, not allowed","text":""},{"location":"sf-deployment-assistant/Invalid-scope-Mine--not-allowed/#detection","title":"Detection","text":"
  • String: Invalid scope:Mine, not allowed
"},{"location":"sf-deployment-assistant/Invalid-scope-Mine--not-allowed/#resolution","title":"Resolution","text":"
Replace Mine by Everything in the list view SFDX source XML.\nHave a look at this command to manage that automatically :)\nhttps://sfdx-hardis.cloudity.com/hardis/org/fix/listviewmine/ \n
"},{"location":"sf-deployment-assistant/Invalid-type/","title":"Invalid type","text":"

title: \"Invalid type (Deployment assistant)\" description: \"How to solve Salesforce deployment error \\\"Error (.) Invalid type: (.) ((.*))\\\"\"

"},{"location":"sf-deployment-assistant/Invalid-type/#invalid-type","title":"Invalid type","text":""},{"location":"sf-deployment-assistant/Invalid-type/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Invalid type: (.*) \\((.*)\\)
"},{"location":"sf-deployment-assistant/Invalid-type/#resolution","title":"Resolution","text":"
Apex error in {1} with unknown type {2} at position {3}. If {2} is a class name, try to fix it, or maybe it is missing in the files or in package.xml !\n
"},{"location":"sf-deployment-assistant/Mandatory-custom-field-can-not-be-in-a-profile-permission-set/","title":"Mandatory custom field can not be in a profile/permission set (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Mandatory-custom-field-can-not-be-in-a-profile-permission-set/#mandatory-custom-field-can-not-be-in-a-profilepermission-set","title":"Mandatory custom field can not be in a profile/permission set","text":""},{"location":"sf-deployment-assistant/Mandatory-custom-field-can-not-be-in-a-profile-permission-set/#detection","title":"Detection","text":"
  • RegExp: Error (.*) You cannot deploy to a required field: (.*)
"},{"location":"sf-deployment-assistant/Mandatory-custom-field-can-not-be-in-a-profile-permission-set/#resolution","title":"Resolution","text":"
- Search for {2} in source file XML of {1}, then remove the entries matching the results\nExample of element to delete:\n<fieldPermissions>\n  <editable>true</editable>\n  <field>{2}</field>\n  <readable>true</readable>\n</fieldPermissions>\n
"},{"location":"sf-deployment-assistant/Missing-Data-Category-Group/","title":"Missing Data Category Group (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-Data-Category-Group/#missing-data-category-group","title":"Missing Data Category Group","text":""},{"location":"sf-deployment-assistant/Missing-Data-Category-Group/#detection","title":"Detection","text":"
  • RegExp: Error (.*) In field: DeveloperName - no DataCategoryGroup named (.*) found
"},{"location":"sf-deployment-assistant/Missing-Data-Category-Group/#resolution","title":"Resolution","text":"
If Data Category Group {2} is not existing yet in target org, you might need to:\n- create it manually in target org before deployment\n- comment DataCategoryGroup in {1} XML\n
"},{"location":"sf-deployment-assistant/Missing-Feature-Work-Com/","title":"Missing Feature Work.Com (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-Feature-Work-Com/#missing-feature-workcom","title":"Missing Feature Work.Com","text":""},{"location":"sf-deployment-assistant/Missing-Feature-Work-Com/#detection","title":"Detection","text":"
  • String: WorkBadgeDefinition
"},{"location":"sf-deployment-assistant/Missing-Feature-Work-Com/#resolution","title":"Resolution","text":"
Work.com feature must be activated in the target org.\n- Org & Scratch: https://developer.salesforce.com/docs/atlas.en-us.workdotcom_dev_guide.meta/workdotcom_dev_guide/wdc_cc_setup_dev_org.htm\n
"},{"location":"sf-deployment-assistant/Missing-Quick-Action/","title":"Missing Quick Action (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-Quick-Action/#missing-quick-action","title":"Missing Quick Action","text":""},{"location":"sf-deployment-assistant/Missing-Quick-Action/#detection","title":"Detection","text":"
  • RegExp: Error (.*) In field: QuickAction - no QuickAction named (.*) found
"},{"location":"sf-deployment-assistant/Missing-Quick-Action/#resolution","title":"Resolution","text":"
QuickAction {2} referred in {1} is unknown. You can either:\n- Make sure your QuickAction {2} is present in source files and in package.xml\n- If {2} is a standard QuickAction, activate related feature in target org\n- Solve other errors that could impact QuickAction {2}\n- Remove QuickAction {2} in the source XML of {1}. Example of XML to remove below:\n<quickActionListItems>\n  <quickActionName>FeedItem.RypplePost</quickActionName>\n</quickActionListItems>\n
"},{"location":"sf-deployment-assistant/Missing-Sales-Team/","title":"Missing Sales Team (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-Sales-Team/#missing-sales-team","title":"Missing Sales Team","text":""},{"location":"sf-deployment-assistant/Missing-Sales-Team/#detection","title":"Detection","text":"
  • String: related list:RelatedAccountSalesTeam
"},{"location":"sf-deployment-assistant/Missing-Sales-Team/#resolution","title":"Resolution","text":"
Account Teams must be activated in the target org.\n- Org: Setup -> Account Teams -> Enable\n- Scratch org setting:\n\"accountSettings\": {\n  \"enableAccountTeams\": true\n}\n}\n
"},{"location":"sf-deployment-assistant/Missing-e-mail-template/","title":"Missing e-mail template (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-e-mail-template/#missing-e-mail-template","title":"Missing e-mail template","text":""},{"location":"sf-deployment-assistant/Missing-e-mail-template/#detection","title":"Detection","text":"
  • RegExp: In field: template - no EmailTemplate named (.*) found
"},{"location":"sf-deployment-assistant/Missing-e-mail-template/#resolution","title":"Resolution","text":"
An email template should be present in the sources. To retrieve it, you can run:\nsf project retrieve start -m EmailTemplate:{1} -o YOUR_ORG_USERNAME\n
"},{"location":"sf-deployment-assistant/Missing-feature-Chatter-Collaboration-Group/","title":"Missing feature Chatter Collaboration Group (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-feature-Chatter-Collaboration-Group/#missing-feature-chatter-collaboration-group","title":"Missing feature Chatter Collaboration Group","text":""},{"location":"sf-deployment-assistant/Missing-feature-Chatter-Collaboration-Group/#detection","title":"Detection","text":"
  • String: CollaborationGroup
"},{"location":"sf-deployment-assistant/Missing-feature-Chatter-Collaboration-Group/#resolution","title":"Resolution","text":"
Quotes must be activated in the target org.\n- Org: Setup -> Chatter settings -> Allow Records in Groups\n- Scratch org setting:\n\"chatterSettings\": {\n  \"allowRecordsInChatterGroup\": true\n},\n
"},{"location":"sf-deployment-assistant/Missing-feature-ContactToMultipleAccounts/","title":"Missing feature ContactToMultipleAccounts (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-feature-ContactToMultipleAccounts/#missing-feature-contacttomultipleaccounts","title":"Missing feature ContactToMultipleAccounts","text":""},{"location":"sf-deployment-assistant/Missing-feature-ContactToMultipleAccounts/#detection","title":"Detection","text":"
  • String: no CustomObject named AccountContactRelation found
  • String: Invalid field:ACCOUNT.NAME in related list:RelatedContactAccountRelationList
"},{"location":"sf-deployment-assistant/Missing-feature-ContactToMultipleAccounts/#resolution","title":"Resolution","text":"
Contacts to multiple accounts be activated in the target org.\n- Help: https://help.salesforce.com/articleView?id=sf.shared_contacts_set_up.htm&type=5\n- Scratch org setting:\n\"features\": [\"ContactsToMultipleAccounts\"]\n
"},{"location":"sf-deployment-assistant/Missing-feature-Enhanced-notes/","title":"Missing feature Enhanced notes (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-feature-Enhanced-notes/#missing-feature-enhanced-notes","title":"Missing feature Enhanced notes","text":""},{"location":"sf-deployment-assistant/Missing-feature-Enhanced-notes/#detection","title":"Detection","text":"
  • String: FeedItem.ContentNote
"},{"location":"sf-deployment-assistant/Missing-feature-Enhanced-notes/#resolution","title":"Resolution","text":"
Enhanced Notes must be activated in the target org.\n- Org: Setup -> Notes settings -> Enable Notes\n- Scratch org setting:\n\"enhancedNotesSettings\": {\n  \"enableEnhancedNotes\": true\n},\n
"},{"location":"sf-deployment-assistant/Missing-feature-Ideas-notes/","title":"Missing feature Ideas notes (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-feature-Ideas-notes/#missing-feature-ideas-notes","title":"Missing feature Ideas notes","text":""},{"location":"sf-deployment-assistant/Missing-feature-Ideas-notes/#detection","title":"Detection","text":"
  • String: Idea.InternalIdeasIdeaRecordType
"},{"location":"sf-deployment-assistant/Missing-feature-Ideas-notes/#resolution","title":"Resolution","text":"
Ideas must be activated in the target org.\n- Org: https://help.salesforce.com/articleView?id=networks_enable_ideas.htm&type=0\n- Scratch org setting:\n\"ideasSettings\": {\n  \"enableIdeas\": true\n}\n
"},{"location":"sf-deployment-assistant/Missing-feature-Live-Agent/","title":"Missing feature Live Agent (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-feature-Live-Agent/#missing-feature-live-agent","title":"Missing feature Live Agent","text":""},{"location":"sf-deployment-assistant/Missing-feature-Live-Agent/#detection","title":"Detection","text":"
  • String: FeedItem.ContentNote
"},{"location":"sf-deployment-assistant/Missing-feature-Live-Agent/#resolution","title":"Resolution","text":"
Live Agent must be activated in the target org.\n- Org: Setup -> Live Agent Settings -> Enable Live Agent\n- Scratch org feature: LiveAgent\n
"},{"location":"sf-deployment-assistant/Missing-feature-Opportunity-Teams/","title":"Missing feature Opportunity Teams (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-feature-Opportunity-Teams/#missing-feature-opportunity-teams","title":"Missing feature Opportunity Teams","text":""},{"location":"sf-deployment-assistant/Missing-feature-Opportunity-Teams/#detection","title":"Detection","text":"
  • String: OpportunityTeam
"},{"location":"sf-deployment-assistant/Missing-feature-Opportunity-Teams/#resolution","title":"Resolution","text":"
Opportunity Teams must be activated in the target org.\n- Org: Setup -> Opportunity Team Settings -> Enable Team Selling\n- Scratch org:\n\"opportunitySettings\": {\n  \"enableOpportunityTeam\": true\n}\n
"},{"location":"sf-deployment-assistant/Missing-feature-Product-Request/","title":"Missing feature Product Request (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-feature-Product-Request/#missing-feature-product-request","title":"Missing feature Product Request","text":""},{"location":"sf-deployment-assistant/Missing-feature-Product-Request/#detection","title":"Detection","text":"
  • String: ProductRequest
"},{"location":"sf-deployment-assistant/Missing-feature-Product-Request/#resolution","title":"Resolution","text":"
ProductRequest object is not available in the target org.\nMaybe you would like to clean its references within Profiles / PS using the following command ?\nsf hardis:project:clean:references , then select \"ProductRequest references\"\n
"},{"location":"sf-deployment-assistant/Missing-feature-Social-Customer-Service/","title":"Missing feature Social Customer Service (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-feature-Social-Customer-Service/#missing-feature-social-customer-service","title":"Missing feature Social Customer Service","text":""},{"location":"sf-deployment-assistant/Missing-feature-Social-Customer-Service/#detection","title":"Detection","text":"
  • String: SocialPersona.AreWeFollowing
"},{"location":"sf-deployment-assistant/Missing-feature-Social-Customer-Service/#resolution","title":"Resolution","text":"
Social Custom Service must be activated in the target org.\n- Org: Setup -> https://help.salesforce.com/articleView?id=sf.social_customer_service_setup_enable.htm&type=5\n- Scratch org feature: SocialCustomerService\n
"},{"location":"sf-deployment-assistant/Missing-feature-Translation-Workbench/","title":"Missing feature Translation Workbench (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-feature-Translation-Workbench/#missing-feature-translation-workbench","title":"Missing feature Translation Workbench","text":""},{"location":"sf-deployment-assistant/Missing-feature-Translation-Workbench/#detection","title":"Detection","text":"
  • RegExp: report-meta.xml(.*)filterlanguage
"},{"location":"sf-deployment-assistant/Missing-feature-Translation-Workbench/#resolution","title":"Resolution","text":"
Translation workbench must be activated in the target org.\n- Org: Setup -> https://help.salesforce.com/articleView?id=sf.customize_wbench.htm&type=5\n- Scratch org:\n\"languageSettings\": {\n  \"enableTranslationWorkbench\":  true,\n  \"enableEndUserLanguages\": true\n}\n
"},{"location":"sf-deployment-assistant/Missing-field-MiddleName/","title":"Missing field MiddleName (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-field-MiddleName/#missing-field-middlename","title":"Missing field MiddleName","text":""},{"location":"sf-deployment-assistant/Missing-field-MiddleName/#detection","title":"Detection","text":"
  • String: field MiddleName
  • String: Variable does not exist: MiddleName
"},{"location":"sf-deployment-assistant/Missing-field-MiddleName/#resolution","title":"Resolution","text":"
MiddleNames must be activated in the target org.\n- Help: https://help.salesforce.com/articleView?id=000332623&type=1&mode=1\n- Scratch org setting:\n\"nameSettings\": {\n  \"enableMiddleName\": true\n}\n
"},{"location":"sf-deployment-assistant/Missing-field-Suffix/","title":"Missing field Suffix (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-field-Suffix/#missing-field-suffix","title":"Missing field Suffix","text":""},{"location":"sf-deployment-assistant/Missing-field-Suffix/#detection","title":"Detection","text":"
  • String: field Suffix
"},{"location":"sf-deployment-assistant/Missing-field-Suffix/#resolution","title":"Resolution","text":"
Suffix must be activated in the target org.\n- Help: https://help.salesforce.com/articleView?id=000332623&type=1&mode=1\n- Scratch org setting:\n\"nameSettings\": {\n  \"enableNameSuffix\": true\n},\n
"},{"location":"sf-deployment-assistant/Missing-field-SyncedQuoteId/","title":"Missing field SyncedQuoteId (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-field-SyncedQuoteId/#missing-field-syncedquoteid","title":"Missing field SyncedQuoteId","text":""},{"location":"sf-deployment-assistant/Missing-field-SyncedQuoteId/#detection","title":"Detection","text":"
  • String: field SyncedQuoteId
  • String: Error force-app/main/default/objects/Quote/Quote.object-meta.xml
  • String: Error force-app/main/default/objects/Opportunity/fields/SyncedQuoteId.field-meta.xml
"},{"location":"sf-deployment-assistant/Missing-field-SyncedQuoteId/#resolution","title":"Resolution","text":"
Quotes must be activated in the target org.\n- Help: https://help.salesforce.com/articleView?id=sf.quotes_enable.htm&type=5\n- Scratch org setting:\n\"quoteSettings\": {\n  \"enableQuote\": true\n}\n
"},{"location":"sf-deployment-assistant/Missing-multi-currency-field/","title":"Missing multi-currency field (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-multi-currency-field/#missing-multi-currency-field","title":"Missing multi-currency field","text":""},{"location":"sf-deployment-assistant/Missing-multi-currency-field/#detection","title":"Detection","text":"
  • RegExp: A reference to a custom field (.*)CurrencyIsoCode
"},{"location":"sf-deployment-assistant/Missing-multi-currency-field/#resolution","title":"Resolution","text":"
You probably need to activate MultiCurrency (from Setup -> Company information)\n
"},{"location":"sf-deployment-assistant/Missing-object-referenced-in-package-xml/","title":"Missing object referenced in package.xml (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-object-referenced-in-package-xml/#missing-object-referenced-in-packagexml","title":"Missing object referenced in package.xml","text":""},{"location":"sf-deployment-assistant/Missing-object-referenced-in-package-xml/#detection","title":"Detection","text":"
  • RegExp: An object (.*) of type (.*) was named in package.xml, but was not found in zipped directory
"},{"location":"sf-deployment-assistant/Missing-object-referenced-in-package-xml/#resolution","title":"Resolution","text":"
You can either:\n- Update the package.xml to remove the reference to the missing {2} {1}\n- Add the missing {2} {1} in your project source files\n
"},{"location":"sf-deployment-assistant/Missing-profile-default-application/","title":"Missing profile default application (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-profile-default-application/#missing-profile-default-application","title":"Missing profile default application","text":""},{"location":"sf-deployment-assistant/Missing-profile-default-application/#detection","title":"Detection","text":"
  • String: You can't remove the only default app from the profile.
"},{"location":"sf-deployment-assistant/Missing-profile-default-application/#resolution","title":"Resolution","text":"
You must have a default application for a profile. You can:\n - Update it in UI\n - Update the XML of the profile to set \"true\" in the <default> tag of one of the applicationVisibilities item.\n Ex:\n <applicationVisibilities>\n    <application>standard__LightningSales</application>\n    <default>true</default>\n    <visible>true</visible>\n</applicationVisibilities>\n
"},{"location":"sf-deployment-assistant/Missing-report/","title":"Missing report (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Missing-report/#missing-report","title":"Missing report","text":""},{"location":"sf-deployment-assistant/Missing-report/#detection","title":"Detection","text":"
  • RegExp: Error (.*) The (.*) report chart has a problem with the \"reportName\" field
"},{"location":"sf-deployment-assistant/Missing-report/#resolution","title":"Resolution","text":"
{1} is referring to unknown report {2}. To retrieve it, you can run:\n- sf project retrieve start -m Report:{2} -o YOUR_ORG_USERNAME\n- If it fails, looks for the report folder and add it before report name to the retrieve command (ex: MYFOLDER/MYREPORTNAME)\n
"},{"location":"sf-deployment-assistant/Network-issue/","title":"Network issue (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Network-issue/#network-issue","title":"Network issue","text":""},{"location":"sf-deployment-assistant/Network-issue/#detection","title":"Detection","text":"
  • String: ECONNABORTED
  • String: ECONNRESET
"},{"location":"sf-deployment-assistant/Network-issue/#resolution","title":"Resolution","text":"
The network connection has been aborted, this is a purely technical issue.\nTry again, and if you still see errors, check the status of Salesforce instance on https://status.salesforce.com\n
"},{"location":"sf-deployment-assistant/Not-available-for-deploy-for-this-organization/","title":"Not available for deploy for this organization (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Not-available-for-deploy-for-this-organization/#not-available-for-deploy-for-this-organization","title":"Not available for deploy for this organization","text":""},{"location":"sf-deployment-assistant/Not-available-for-deploy-for-this-organization/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Not available for deploy for this organization
"},{"location":"sf-deployment-assistant/Not-available-for-deploy-for-this-organization/#resolution","title":"Resolution","text":"
The user you use for deployments probably lacks of the rights (Profiles, Permission sets...) to manage {1}.\n- Assign the deployment user to the good Permission Sets, or modify its profile rights, then try again\n
"},{"location":"sf-deployment-assistant/Not-valid-sharing-model/","title":"Not valid sharing model (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Not-valid-sharing-model/#not-valid-sharing-model","title":"Not valid sharing model","text":""},{"location":"sf-deployment-assistant/Not-valid-sharing-model/#detection","title":"Detection","text":"
  • RegExp: Error (.*) (.*) is not a valid sharing model for (.*) when (.*) sharing model is (.*)
"},{"location":"sf-deployment-assistant/Not-valid-sharing-model/#resolution","title":"Resolution","text":"
It seems that Sharing Models of {1} and {4} are not compatible in target org.\n- Use compatible sharing models between {1} and {4} by updating Sharing model of {1} or {4}\n- Make sure that sfdx sources {1}.object-meta.xml and {4}.object-meta.xml and in the files, and that {1} and {4} are in package.xml in CustomObject block\n- You may directly update sharingModel in XML. For example, replace <sharingModel>ReadWrite</sharingModel> by <sharingModel>Private</sharingModel> in {3}.object-meta.xml\n
"},{"location":"sf-deployment-assistant/Objects-rights-on-a-role-is-below-org-default/","title":"Objects rights on a role is below org default (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Objects-rights-on-a-role-is-below-org-default/#objects-rights-on-a-role-is-below-org-default","title":"Objects rights on a role is below org default","text":""},{"location":"sf-deployment-assistant/Objects-rights-on-a-role-is-below-org-default/#detection","title":"Detection","text":"
  • String: access level below organization default
"},{"location":"sf-deployment-assistant/Objects-rights-on-a-role-is-below-org-default/#resolution","title":"Resolution","text":"
Your org wide settings default must be lower than the level defined in roles:\n- If you are in a scratch org, it can be fixable using \"objectProperties\" in project-scratch-def.json (see \"Set Object-Level Sharing Settings\" paragraph in page https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_scratch_orgs_def_file.htm)\n- If you are in a sandbox/dev/prod org, you need to update default org wide settings before deployment. See https://www.sfdcpoint.com/salesforce/organization-wide-defaults-owd-in-salesforce/\n
"},{"location":"sf-deployment-assistant/Picklist-sharing-is-not-supported/","title":"Picklist sharing is not supported (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Picklist-sharing-is-not-supported/#picklist-sharing-is-not-supported","title":"Picklist sharing is not supported","text":""},{"location":"sf-deployment-assistant/Picklist-sharing-is-not-supported/#detection","title":"Detection","text":"
  • String: Picklist sharing is not supported
"},{"location":"sf-deployment-assistant/Picklist-sharing-is-not-supported/#resolution","title":"Resolution","text":"
You probably changed the type of a field.\nGo manually make the change in the target org, so the deployment will pass\n
"},{"location":"sf-deployment-assistant/Picklist-value-not-found/","title":"Picklist value not found (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Picklist-value-not-found/#picklist-value-not-found","title":"Picklist value not found","text":""},{"location":"sf-deployment-assistant/Picklist-value-not-found/#detection","title":"Detection","text":"
  • RegExp: Picklist value: (.*) in picklist: (.*) not found
"},{"location":"sf-deployment-assistant/Picklist-value-not-found/#resolution","title":"Resolution","text":"
Sources have references to value {1} of picklist {2}\n- If picklist {2} is standard, add the picklist to sfdx sources by using \"sf project retrieve start -m StandardValueSet:{2}\", then save again\n- Else, perform a search in all code of {1}, then remove XML tags referring to {1} (for example in record types metadatas)\n
"},{"location":"sf-deployment-assistant/Please-choose-a-different-name/","title":"Please choose a different name (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Please-choose-a-different-name/#please-choose-a-different-name","title":"Please choose a different name","text":""},{"location":"sf-deployment-assistant/Please-choose-a-different-name/#detection","title":"Detection","text":"
  • RegExp: Error (.*) This (.*) already exists or has been previously used(.*)Please choose a different name.
"},{"location":"sf-deployment-assistant/Please-choose-a-different-name/#resolution","title":"Resolution","text":"
- Rename {1} in the target org, then try again the deployment. if it succeeds, delete the renamed item.\n- or Delete {1} in the target org, then try again the deployment\n
"},{"location":"sf-deployment-assistant/Record-Type-not-found/","title":"Record Type not found (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Record-Type-not-found/#record-type-not-found","title":"Record Type not found","text":""},{"location":"sf-deployment-assistant/Record-Type-not-found/#detection","title":"Detection","text":"
  • RegExp: Error (.*) In field: recordType - no RecordType named (.*) found
"},{"location":"sf-deployment-assistant/Record-Type-not-found/#resolution","title":"Resolution","text":"
An unknown record type {2} is referenced in {1}\n- If record type {2} is not supposed to exist, perform a search in all files of {1}, then remove matching XML elements referring to this record type\n- If record type {2} is supposed to exist, you may have to create it manually in the target org to make the deployment pass\n
"},{"location":"sf-deployment-assistant/Send-email-is-disabled/","title":"Send email is disabled (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Send-email-is-disabled/#send-email-is-disabled","title":"Send email is disabled","text":""},{"location":"sf-deployment-assistant/Send-email-is-disabled/#detection","title":"Detection","text":"
  • String: Send Email is disabled or activities are not allowed
  • String: Unknown user permission: SendExternalEmailAvailable
"},{"location":"sf-deployment-assistant/Send-email-is-disabled/#resolution","title":"Resolution","text":"
Go to Email -> Deliverability -> Select value \"All emails\"\n
"},{"location":"sf-deployment-assistant/Sharing-recalculation-lock/","title":"Sharing recalculation lock (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Sharing-recalculation-lock/#sharing-recalculation-lock","title":"Sharing recalculation lock","text":""},{"location":"sf-deployment-assistant/Sharing-recalculation-lock/#detection","title":"Detection","text":"
  • String: because it interferes with another operation already in progress
  • String: Le calcul de partage demand\u00e9 ne peut \u00eatre trait\u00e9 maintenant car il interf\u00e8re avec une autre op\u00e9ration en cours
"},{"location":"sf-deployment-assistant/Sharing-recalculation-lock/#resolution","title":"Resolution","text":"
If you changed a field from MasterDetail to Lookup, you must do it manually in the target org before being able to deploy\n
"},{"location":"sf-deployment-assistant/Sort-order-must-be-in-sequential-order/","title":"Sort order must be in sequential order (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Sort-order-must-be-in-sequential-order/#sort-order-must-be-in-sequential-order","title":"Sort order must be in sequential order","text":""},{"location":"sf-deployment-assistant/Sort-order-must-be-in-sequential-order/#detection","title":"Detection","text":"
  • RegExp: Error (.*) SortOrder must be in sequential order from
"},{"location":"sf-deployment-assistant/Sort-order-must-be-in-sequential-order/#resolution","title":"Resolution","text":"
You probably have a default DuplicateRule in the target org. Retrieve it from target org, or delete it manually in target org, so you can deploy.\nRef: https://developer.salesforce.com/forums/?id=9060G000000I6SoQAK\n
"},{"location":"sf-deployment-assistant/Tableau-CRM---Wave-digest-error/","title":"Tableau CRM / Wave digest error (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Tableau-CRM---Wave-digest-error/#tableau-crm-wave-digest-error","title":"Tableau CRM / Wave digest error","text":""},{"location":"sf-deployment-assistant/Tableau-CRM---Wave-digest-error/#detection","title":"Detection","text":"
  • String: Fix the sfdcDigest node errors and then upload the file again
"},{"location":"sf-deployment-assistant/Tableau-CRM---Wave-digest-error/#resolution","title":"Resolution","text":"
Go to the target org, open profile \"Analytics Cloud Integration User\" and add READ rights to the missing object fields \n
"},{"location":"sf-deployment-assistant/Test-classes-with-0--coverage/","title":"Test classes with 0% coverage (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Test-classes-with-0--coverage/#test-classes-with-0-coverage","title":"Test classes with 0% coverage","text":""},{"location":"sf-deployment-assistant/Test-classes-with-0--coverage/#detection","title":"Detection","text":"
  • RegExp: 0%
"},{"location":"sf-deployment-assistant/Test-classes-with-0--coverage/#resolution","title":"Resolution","text":"
Please make sure that none of the test classes are 0% covered\n
"},{"location":"sf-deployment-assistant/Unknown-user-permission--CreateAuditFields/","title":"Unknown user permission: CreateAuditFields (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Unknown-user-permission--CreateAuditFields/#unknown-user-permission-createauditfields","title":"Unknown user permission: CreateAuditFields","text":""},{"location":"sf-deployment-assistant/Unknown-user-permission--CreateAuditFields/#detection","title":"Detection","text":"
  • String: Unknown user permission: CreateAuditFields
"},{"location":"sf-deployment-assistant/Unknown-user-permission--CreateAuditFields/#resolution","title":"Resolution","text":"
You need to enable the \"Create audit field\" permission in the target org\nPlease check https://help.salesforce.com/articleView?id=000334139&type=1&mode=1\n
"},{"location":"sf-deployment-assistant/Unknown-user-permission--FieldServiceAccess/","title":"Unknown user permission: FieldServiceAccess (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Unknown-user-permission--FieldServiceAccess/#unknown-user-permission-fieldserviceaccess","title":"Unknown user permission: FieldServiceAccess","text":""},{"location":"sf-deployment-assistant/Unknown-user-permission--FieldServiceAccess/#detection","title":"Detection","text":"
  • String: Unknown user permission: FieldServiceAccess
"},{"location":"sf-deployment-assistant/Unknown-user-permission--FieldServiceAccess/#resolution","title":"Resolution","text":"
You need to enable the \"Field Service Access\" permission in the target org\nPlease check https://help.salesforce.com/articleView?id=sf.fs_enable.htm&type=5\n
"},{"location":"sf-deployment-assistant/Unknown-user-permission/","title":"Unknown user permission (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Unknown-user-permission/#unknown-user-permission","title":"Unknown user permission","text":""},{"location":"sf-deployment-assistant/Unknown-user-permission/#detection","title":"Detection","text":"
  • String: Unknown user permission:
"},{"location":"sf-deployment-assistant/Unknown-user-permission/#resolution","title":"Resolution","text":"
You can:\n- enable the related permission in the target org\n- or remove references to the permission in source XML files (Probably a Profile or a Permission set)\n
"},{"location":"sf-deployment-assistant/Unsupported-sharing-configuration/","title":"Unsupported sharing configuration (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Unsupported-sharing-configuration/#unsupported-sharing-configuration","title":"Unsupported sharing configuration","text":""},{"location":"sf-deployment-assistant/Unsupported-sharing-configuration/#detection","title":"Detection","text":"
  • RegExp: not supported for (.*) since it's org wide default is
"},{"location":"sf-deployment-assistant/Unsupported-sharing-configuration/#resolution","title":"Resolution","text":"
Consistency error between {1} sharing settings and {1} object configuration\nPlease check https://salesforce.stackexchange.com/questions/260923/sfdx-deploying-contact-sharing-rules-on-a-fresh-deployment\nIf you already did that, please try again to run the job\n
"},{"location":"sf-deployment-assistant/Variable-does-not-exist/","title":"Variable does not exist","text":"

title: \"Variable does not exist (Deployment assistant)\" description: \"How to solve Salesforce deployment error \\\"Error (.) Variable does not exist: (.) ((.*))\\\"\"

"},{"location":"sf-deployment-assistant/Variable-does-not-exist/#variable-does-not-exist","title":"Variable does not exist","text":""},{"location":"sf-deployment-assistant/Variable-does-not-exist/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Variable does not exist: (.*) \\((.*)\\)
"},{"location":"sf-deployment-assistant/Variable-does-not-exist/#resolution","title":"Resolution","text":"
Apex error in {1} with unknown variable {2} at position {3}. If {2} is a class name, try to fix it, or maybe it is missing in the files or in package.xml !\n
"},{"location":"sf-deployment-assistant/Visibility-is-not-allowed-for-type/","title":"Visibility is not allowed for type (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/Visibility-is-not-allowed-for-type/#visibility-is-not-allowed-for-type","title":"Visibility is not allowed for type","text":""},{"location":"sf-deployment-assistant/Visibility-is-not-allowed-for-type/#detection","title":"Detection","text":"
  • RegExp: Error (.*) set the visibility for a (.*) to Protected unless you are in a developer
"},{"location":"sf-deployment-assistant/Visibility-is-not-allowed-for-type/#resolution","title":"Resolution","text":"
Update the visibility of {1} to \"Public\"\n
"},{"location":"sf-deployment-assistant/XML-item-appears-more-than-once/","title":"XML item appears more than once (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/XML-item-appears-more-than-once/#xml-item-appears-more-than-once","title":"XML item appears more than once","text":""},{"location":"sf-deployment-assistant/XML-item-appears-more-than-once/#detection","title":"Detection","text":"
  • RegExp: Error (.*) Field:(.*), value:(.*) appears more than once
"},{"location":"sf-deployment-assistant/XML-item-appears-more-than-once/#resolution","title":"Resolution","text":"
You probably made an error while merging conflicts\nLook for {3} in the XML of {1}\nIf you see two {2} XML blocks with {3}, please decide which one you keep and remove the other one\n
"},{"location":"sf-deployment-assistant/sharing-operation-already-in-progress/","title":"sharing operation already in progress (Deployment assistant)","text":""},{"location":"sf-deployment-assistant/sharing-operation-already-in-progress/#sharing-operation-already-in-progress","title":"sharing operation already in progress","text":""},{"location":"sf-deployment-assistant/sharing-operation-already-in-progress/#detection","title":"Detection","text":"
  • String: sharing operation already in progress
"},{"location":"sf-deployment-assistant/sharing-operation-already-in-progress/#resolution","title":"Resolution","text":"
You can not deploy multiple SharingRules at the same time. You can either:\n- Remove SharingOwnerRules and SharingRule from package.xml (so it becomes a manual operation)\n- Use sf hardis:work:save to generate a deploymentPlan in .sfdx-hardis.json,\n- If you are trying to create a scratch org, add DeferSharingCalc in features in project-scratch-def.json\n
"}]} \ No newline at end of file diff --git a/sf-deployment-assistant/A-sharing-rule-may-be-useless/index.html b/sf-deployment-assistant/A-sharing-rule-may-be-useless/index.html new file mode 100644 index 000000000..d5359e899 --- /dev/null +++ b/sf-deployment-assistant/A-sharing-rule-may-be-useless/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + A sharing rule may be useless (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

A sharing rule may be useless

+

Detection

+
    +
  • String: Required field is missing: sharingCriteriaRules
  • +
+

Resolution

+
Are you sure you need this sharing rule ? You may remove it from the sfdx project
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/API-Version-error/index.html b/sf-deployment-assistant/API-Version-error/index.html new file mode 100644 index 000000000..0bb7e0ac5 --- /dev/null +++ b/sf-deployment-assistant/API-Version-error/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + API Version error (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

API Version error

+

Detection

+
    +
  • RegExp: Error (.*) The (.*) apiVersion can't be "([0-9]+)"
  • +
+

Resolution

+
{1} metadata has probably been created/updated in a sandbox already upgraded to next platform version (ex: Sandbox in Summer'23 and Production in Spring'23)
+- First, try to update the api version in the XML of {1} metadata file (decrement the number in <apiVersion>{3}.0</apiVersion>)
+- If it still doesn't work because the metadata structure has changed between version, you may try a sf project:retrieve:start of the metadata by forcing --api-version at the end of the command.
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Allow-deployment-with-pending-Apex-Jobs/index.html b/sf-deployment-assistant/Allow-deployment-with-pending-Apex-Jobs/index.html new file mode 100644 index 000000000..b0692ae5e --- /dev/null +++ b/sf-deployment-assistant/Allow-deployment-with-pending-Apex-Jobs/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Allow deployment with pending Apex Jobs (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Allow deployment with pending Apex Jobs

+

Detection

+
    +
  • String: You can bypass this error by allowing deployments with Apex jobs in the Deployment Settings page in Setup.
  • +
+

Resolution

+
Go to target org, in Setup -> Deployment Settings -> Activate option "Allow deployments of components when corresponding Apex jobs are pending or in progress."
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Async-exception-in-test-class/index.html b/sf-deployment-assistant/Async-exception-in-test-class/index.html new file mode 100644 index 000000000..157682f3a --- /dev/null +++ b/sf-deployment-assistant/Async-exception-in-test-class/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Async exception in test class (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Async exception in test class

+

Detection

+
    +
  • RegExp: System.AsyncException: (.*) Apex
  • +
+

Resolution

+
This may be a test class implementation issue in {1}.
+Please check https://developer.salesforce.com/forums/?id=9060G0000005kVLQAY
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/CRM-Analytics--A-Recipe-must-specify-a-DataFlow/index.html b/sf-deployment-assistant/CRM-Analytics--A-Recipe-must-specify-a-DataFlow/index.html new file mode 100644 index 000000000..0607ed95e --- /dev/null +++ b/sf-deployment-assistant/CRM-Analytics--A-Recipe-must-specify-a-DataFlow/index.html @@ -0,0 +1,7623 @@ + + + + + + + + + + + + + + + + + + + + + + + + + CRM Analytics: A Recipe must specify a DataFlow (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

CRM Analytics: A Recipe must specify a DataFlow

+

Detection

+
    +
  • RegExp: Error (.*) A Recipe must specify a Dataflow
  • +
+

Resolution

+
You must include related WaveDataFlow {1} in sources (and probably in package.xml too).
+To retrieve it, run: sf project retrieve start -m WaveDataFlow:{1} -u SOURCE_ORG_USERNAME
+You can also retrieve all analytics sources in one shot using sf hardis:org:retrieve:source:analytics -u SOURCE_ORG_USERNAME
+  - https://salesforce.stackexchange.com/a/365453/33522
+  - https://help.salesforce.com/s/articleView?id=000319274&type=1
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Campaign-can-not-be-updated/index.html b/sf-deployment-assistant/Campaign-can-not-be-updated/index.html new file mode 100644 index 000000000..81a3a8b2c --- /dev/null +++ b/sf-deployment-assistant/Campaign-can-not-be-updated/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Campaign can not be updated - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +
+

title: "Campaign can not be updated (Deployment assistant)" +description: "How to solve Salesforce deployment error \"The object "Campaign" can't be updated\""

+
+ +

Campaign can not be updated

+

Detection

+
    +
  • String: The object "Campaign" can't be updated
  • +
+

Resolution

+
Add "MarketingUser" in project-scratch-def.json features
+If it is already done, you may manually check "MarketingUser" field on the scratch org user
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Can-not-change-field-type-to-a-formula-field/index.html b/sf-deployment-assistant/Can-not-change-field-type-to-a-formula-field/index.html new file mode 100644 index 000000000..09b5cbb43 --- /dev/null +++ b/sf-deployment-assistant/Can-not-change-field-type-to-a-formula-field/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Can not change field type to a formula field (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Can not change field type to a formula field

+

Detection

+
    +
  • RegExp: Error (.*) Cannot update a field from a Formula to something else
  • +
+

Resolution

+
You need to manually delete or rename the field in the target org to allow the deployment to pass
+- First, try to manually delete field {1} in the target org
+- if you can't delete {1}, rename it into {1}_ToDel, then once the deployment done, delete {1}_ToDel
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Can-not-change-field-type-with-picklist/index.html b/sf-deployment-assistant/Can-not-change-field-type-with-picklist/index.html new file mode 100644 index 000000000..939917483 --- /dev/null +++ b/sf-deployment-assistant/Can-not-change-field-type-with-picklist/index.html @@ -0,0 +1,7622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Can not change field type with picklist (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Can not change field type with picklist

+

Detection

+
    +
  • RegExp: Error (.*) Cannot change which global value set this picklist uses
  • +
+

Resolution

+
You probably updated the type of field {1}, and Salesforce does not allows that with deployments. You can:
+- Try to manually change the type of {1} directly in target org, but it may not be technically possible
+- Delete field {1} in target org: it will be recreated after deployment (but you will loose data on existing records, so be careful if your target is a production org)
+- Create another field with desired type and manage data recovery if the target is a production org
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Can-not-change-type-due-to-existing-data/index.html b/sf-deployment-assistant/Can-not-change-type-due-to-existing-data/index.html new file mode 100644 index 000000000..b1c099488 --- /dev/null +++ b/sf-deployment-assistant/Can-not-change-type-due-to-existing-data/index.html @@ -0,0 +1,7624 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Can not change type due to existing data (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Can not change type due to existing data

+

Detection

+
    +
  • RegExp: Error (.*) Cannot change type due to existing data
  • +
+

Resolution

+
It is usually not recommended to change types of fields, but if it's really necessary you can:
+- Manually change the type of {1} in the target org
+- If you can't manually change the type:
+  - you may modify the dependencies (Formulas, Flows...) using {1}, so they don't use this field
+  - you can also delete dependencies (Formulas, Flows...) using {1}, but make sure they are deployed again later
+- More help: https://help.salesforce.com/s/articleView?id=000327186&type=1
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Can-not-delete-custom-field/index.html b/sf-deployment-assistant/Can-not-delete-custom-field/index.html new file mode 100644 index 000000000..3c5a66f53 --- /dev/null +++ b/sf-deployment-assistant/Can-not-delete-custom-field/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Can not delete custom field (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Can not delete custom field

+

Detection

+
    +
  • RegExp: This (.*) is referenced elsewhere in salesforce.com
  • +
  • RegExp: Le champ personnalisé (.*) est utilisé dans (.*)
  • +
+

Resolution

+
Custom field {1} can not be deleted because it is used elsewhere. Remove its references ans try again
+THIS MAY BE A FALSE POSITIVE if you are just testing the deployment, as destructiveChanges are deployed separately from updated items deployment check
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Can-not-delete-record-type/index.html b/sf-deployment-assistant/Can-not-delete-record-type/index.html new file mode 100644 index 000000000..3f5e9085e --- /dev/null +++ b/sf-deployment-assistant/Can-not-delete-record-type/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Can not delete record type (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Can not delete record type

+

Detection

+
    +
  • RegExp: Error (.*) Cannot delete record type through API
  • +
+

Resolution

+
You need to manually delete record type {1} in target org
+- Edit record type {1}, uncheck "Active"
+- Delete record type {1}
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Can-not-find-folder/index.html b/sf-deployment-assistant/Can-not-find-folder/index.html new file mode 100644 index 000000000..348189499 --- /dev/null +++ b/sf-deployment-assistant/Can-not-find-folder/index.html @@ -0,0 +1,7622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Can not find folder (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Can not find folder

+

Detection

+
    +
  • RegExp: Error (.*) Cannot find folder:(.*)
  • +
+

Resolution

+
Folder {2} is missing.
+- If folder {2} is existing in sources, add it in related package.xml
+- If folder {2} is not existing in DX sources, please use sf hardis:project:clean:retrievefolders to retrieve it
+- If both previous solutions did not work, go create manually folder {2} in target org
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Can-not-find-user--2-/index.html b/sf-deployment-assistant/Can-not-find-user--2-/index.html new file mode 100644 index 000000000..781dc3e23 --- /dev/null +++ b/sf-deployment-assistant/Can-not-find-user--2-/index.html @@ -0,0 +1,7622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Can not find user (2) (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Can not find user (2)

+

Detection

+
    +
  • RegExp: Error (.*) In field: (.*) - no User named (.*) found
  • +
+

Resolution

+
You made reference to username {3} in {1}, and it probably does not exist in the target org.
+- Do not use named users, but user public groups for assignments -> https://help.salesforce.com/s/articleView?id=sf.creating_and_editing_groups.htm&type=5
+- or Create matching user {3} in the target deployment org
+- or open {1} metadata and remove the XML part referring to hardcoded username {3}
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Can-not-find-user/index.html b/sf-deployment-assistant/Can-not-find-user/index.html new file mode 100644 index 000000000..6ec4d7cc3 --- /dev/null +++ b/sf-deployment-assistant/Can-not-find-user/index.html @@ -0,0 +1,7630 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Can not find user (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Can not find user

+

Detection

+
    +
  • RegExp: Error (.*) Cannot find a user that matches any of the following usernames
  • +
+

Resolution

+
You made reference to username(s) in {1}, and those users probably do not exist in target org.
+- Do not use named users, but user public groups for assignments -> https://help.salesforce.com/s/articleView?id=sf.creating_and_editing_groups.htm&type=5
+- or Create matching user(s) in the target deployment org
+- or Remove the XML part referring to hardcoded usernames
+
+Example of XML you have to remove in {1}:
+
+<folderShares>
+  <accessLevel>Manage</accessLevel>
+  <sharedTo>nicolas.vuillamy@hardis-scratch-po-tgci-root-develop_20220412_0604.com</sharedTo>
+  <sharedToType>User</sharedToType>
+</folderShares>
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Can-not-test-item-deployment-in-simulation-mode/index.html b/sf-deployment-assistant/Can-not-test-item-deployment-in-simulation-mode/index.html new file mode 100644 index 000000000..fa4fe8204 --- /dev/null +++ b/sf-deployment-assistant/Can-not-test-item-deployment-in-simulation-mode/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Can not test item deployment in simulation mode (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Can not test item deployment in simulation mode

+

Detection

+
    +
  • RegExp: Test only deployment cannot update
  • +
+

Resolution

+
THIS IS A FALSE POSITIVE
+When effective deployment will happen, it should pass
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Cannot-update-a-field-to-a-Summary-from-something-else/index.html b/sf-deployment-assistant/Cannot-update-a-field-to-a-Summary-from-something-else/index.html new file mode 100644 index 000000000..5d1bbcfc4 --- /dev/null +++ b/sf-deployment-assistant/Cannot-update-a-field-to-a-Summary-from-something-else/index.html @@ -0,0 +1,7622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Cannot update a field to a Summary from something else (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Cannot update a field to a Summary from something else

+

Detection

+
    +
  • RegExp: Error (.*) Cannot update a field to a (.*) from something else
  • +
+

Resolution

+
You probably updated the type of field {1} to type {2}, and Salesforce does not allows that with deployments. You can:
+- Try to manually change the type of {1} directly in target org, but it may not be technically possible
+- Delete field {1} in target org: it will be recreated after deployment (but you will loose data on existing records, so be careful if your target is a production org)
+- Create another field with desired type and manage data recovery if the target is a production org
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Change-Matching-Rule/index.html b/sf-deployment-assistant/Change-Matching-Rule/index.html new file mode 100644 index 000000000..90ec532bb --- /dev/null +++ b/sf-deployment-assistant/Change-Matching-Rule/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Change Matching Rule (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Change Matching Rule

+

Detection

+
    +
  • RegExp: Error (.*) Before you change a matching rule, you must deactivate it
  • +
+

Resolution

+
To be able to deploy, you must go in target org setup to manually deactivate matching rule {1}
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Condition-missing-reference/index.html b/sf-deployment-assistant/Condition-missing-reference/index.html new file mode 100644 index 000000000..61a3833c1 --- /dev/null +++ b/sf-deployment-assistant/Condition-missing-reference/index.html @@ -0,0 +1,7622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Condition missing reference - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +
+

title: "Condition missing reference (Deployment assistant)" +description: "How to solve Salesforce deployment error \"Error (.) field integrity exception: unknown (A condition has a reference to (.), which doesn't exist.)\""

+
+ +

Condition missing reference

+

Detection

+
    +
  • RegExp: Error (.*) field integrity exception: unknown \(A condition has a reference to (.*), which doesn't exist.\)
  • +
+

Resolution

+
There is a reference to {2} in {1}, and {2} is not found. You can either:
+- Add {2} in your deployment sources and make sure it is named in package.xml
+- Remove the reference to {2} in {1}
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Couldn-t-retrieve-or-load-information-on-the-field/index.html b/sf-deployment-assistant/Couldn-t-retrieve-or-load-information-on-the-field/index.html new file mode 100644 index 000000000..f13973045 --- /dev/null +++ b/sf-deployment-assistant/Couldn-t-retrieve-or-load-information-on-the-field/index.html @@ -0,0 +1,7622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Couldn t retrieve or load information on the field - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +
+

title: "Couldn't retrieve or load information on the field (Deployment assistant)" +description: "How to solve Salesforce deployment error \"Error (.) Something went wrong. We couldn't retrieve or load the information on the field: (.).\""

+
+ +

Couldn't retrieve or load information on the field

+

Detection

+
    +
  • RegExp: Error (.*) Something went wrong. We couldn't retrieve or load the information on the field: (.*)\.
  • +
+

Resolution

+
There is a reference to {2} in {1}, and {2} is not found. You can either:
+- Commit {2} in your deployment sources and make sure it is named in package.xml
+- Remove the reference to {2} in {1}
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Custom-field-not-found/index.html b/sf-deployment-assistant/Custom-field-not-found/index.html new file mode 100644 index 000000000..5591b827e --- /dev/null +++ b/sf-deployment-assistant/Custom-field-not-found/index.html @@ -0,0 +1,7638 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Custom field not found (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Custom field not found

+

Detection

+
    +
  • RegExp: Error (.*) In field: (.*) - no CustomField named (.*)\.(.*) found
  • +
+

Examples

+
    +
  • Error PS_Admin In field: field - no CustomField named User.expcloud__Portal_Username__c found
  • +
+

Resolution

+
A reference to a custom field {3}.{4} is not found in {1}:
+- If you renamed {3}.{4}, do a search/replace in {1} with previous field name and {4}
+- If you deleted {3}.{4}, or if you don't want to deploy it, do a search on {4} in all sources, and remove all XML elements referring to {3}.{4} (except in destructiveChanges.xml)
+- If {3}.{4} should exist, make sure it is in force-app/main/default/objects/{3}/fields and that {3}.{4} is in manifest/package.xml in CustomField section
+- If {3}.{4} is standard, the error is because {3}.{4} is not available in the org you are trying to deploy to. You can:
+  - Remove the reference to {4} in the XML of {1} ( maybe sf hardis:project:clean:references can clean automatically for you ! )
+  - Activate the required features/license in the target org
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Custom-metadata-entry-not-found/index.html b/sf-deployment-assistant/Custom-metadata-entry-not-found/index.html new file mode 100644 index 000000000..44569e08d --- /dev/null +++ b/sf-deployment-assistant/Custom-metadata-entry-not-found/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Custom metadata entry not found (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Custom metadata entry not found

+

Detection

+
    +
  • RegExp: Error (.*) In field: (.*) - no CustomMetadata named (.*) found
  • +
+

Resolution

+
A reference to a custom metadata {3} of type {2} is not found in {1}:
+- Are you sure you deployed {3} ?
+- If you use a package.xml, is {3} present within type CustomMetadata ?
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Custom-object-not-found/index.html b/sf-deployment-assistant/Custom-object-not-found/index.html new file mode 100644 index 000000000..cc7812776 --- /dev/null +++ b/sf-deployment-assistant/Custom-object-not-found/index.html @@ -0,0 +1,7623 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Custom object not found (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Custom object not found

+

Detection

+
    +
  • RegExp: Error (.*) In field: field - no CustomObject named (.*) found
  • +
+

Resolution

+
A reference to a custom object {2} is not found in {1}:
+- If you renamed the custom object, do a search/replace in sources with previous object name and new object name
+- If you deleted the custom object, or if you don't want to deploy it, do a search on the custom object name, and remove XML elements referencing it
+- If the object should exist, make sure it is in force-app/main/default/objects and that the object name is in manifest/package.xml in CustomObject section
+You may also have a look to command sf hardis:project:clean:references
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Dependent-class-is-invalid-and-needs-recompilation/index.html b/sf-deployment-assistant/Dependent-class-is-invalid-and-needs-recompilation/index.html new file mode 100644 index 000000000..e897d7230 --- /dev/null +++ b/sf-deployment-assistant/Dependent-class-is-invalid-and-needs-recompilation/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Dependent class is invalid and needs recompilation (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Dependent class is invalid and needs recompilation

+

Detection

+
    +
  • RegExp: Error (.*) Dependent class is invalid and needs recompilation
  • +
+

Resolution

+
Solve the other errors and this one will disappear !
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Duplicate-label/index.html b/sf-deployment-assistant/Duplicate-label/index.html new file mode 100644 index 000000000..5f0ee1aae --- /dev/null +++ b/sf-deployment-assistant/Duplicate-label/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Duplicate label (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Duplicate label

+

Detection

+
    +
  • RegExp: Error (.*) Duplicate label: (.*)
  • +
+

Resolution

+
You probably renamed the picklist API name for {2}. Please update manually the picklist {1} in the target org to avoid to have a duplicate label
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Duplicate-value-Platform-Action-Id-List/index.html b/sf-deployment-assistant/Duplicate-value-Platform-Action-Id-List/index.html new file mode 100644 index 000000000..9f92ca22f --- /dev/null +++ b/sf-deployment-assistant/Duplicate-value-Platform-Action-Id-List/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Duplicate value Platform Action Id List (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Duplicate value Platform Action Id List

+

Detection

+
    +
  • String: duplicate value found: PlatformActionListId duplicates value on record with id
  • +
+

Resolution

+
There are probably issue with conflict management. Open the XML of the source item, and replace all <sortOrder> numbers to make an ascending order, starting with 0
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Empty-source-items/index.html b/sf-deployment-assistant/Empty-source-items/index.html new file mode 100644 index 000000000..da22aba61 --- /dev/null +++ b/sf-deployment-assistant/Empty-source-items/index.html @@ -0,0 +1,7622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Empty source items (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Empty source items

+

Detection

+
    +
  • String: Required field is missing: sharingOwnerRules
  • +
  • String: Required field is missing: standardValue
  • +
  • String: Required field is missing: valueTranslation
  • +
+

Resolution

+
You probably retrieved empty items, that must not be included within the SFDX project
+To remove them, please run sfdx:hardis:project:clean:emptyitems
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Enable-CRM-Analytics/index.html b/sf-deployment-assistant/Enable-CRM-Analytics/index.html new file mode 100644 index 000000000..70b966efa --- /dev/null +++ b/sf-deployment-assistant/Enable-CRM-Analytics/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Enable CRM Analytics (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Enable CRM Analytics

+

Detection

+
    +
  • String: It should be created by enabling the CRM Analytics Cloud preference
  • +
+

Resolution

+
You must enable CRM Analytics (ex Wave, Einstein Analytics & Tableau CRM) in the target org.
+You probably also need to add CRM Analytics Admin Permission Set assignment to the deployment user
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Error-parsing-file/index.html b/sf-deployment-assistant/Error-parsing-file/index.html new file mode 100644 index 000000000..f33db1572 --- /dev/null +++ b/sf-deployment-assistant/Error-parsing-file/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Error parsing file (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Error parsing file

+

Detection

+
    +
  • RegExp: Error (.*) Error parsing file: (.*)
  • +
+

Resolution

+
There has been an error parsing the XML file of {1}: {2}
+- Open file {1} and look where the error can be ! (merge issue, typo, XML tag not closed...)
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Expired-Access---Refresh-Token/index.html b/sf-deployment-assistant/Expired-Access---Refresh-Token/index.html new file mode 100644 index 000000000..b8dafef63 --- /dev/null +++ b/sf-deployment-assistant/Expired-Access---Refresh-Token/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Expired Access / Refresh Token (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Expired Access / Refresh Token

+

Detection

+
    +
  • String: expired access/refresh token
  • +
+

Resolution

+
Run command "Select another org" from Status panel (or sf hardis:org:select) to authenticate again to your org
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Field-not-available-for-element/index.html b/sf-deployment-assistant/Field-not-available-for-element/index.html new file mode 100644 index 000000000..e6226871c --- /dev/null +++ b/sf-deployment-assistant/Field-not-available-for-element/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Field not available for element (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Field not available for element

+

Detection

+
    +
  • RegExp: Field (.*) is not available for
  • +
+

Resolution

+
You probably changed the type of field {1}.
+Find field {1} in the source XML, and remove the section using it
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Flow-must-be-deleted-manually/index.html b/sf-deployment-assistant/Flow-must-be-deleted-manually/index.html new file mode 100644 index 000000000..3f04f157c --- /dev/null +++ b/sf-deployment-assistant/Flow-must-be-deleted-manually/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Flow must be deleted manually (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Flow must be deleted manually

+

Detection

+
    +
  • RegExp: .flow (.*) insufficient access rights on cross-reference id
  • +
+

Resolution

+
Flow {1} can not be deleted using deployments, please delete it manually in the target org using menu Setup -> Flows , context menu on {1} -> View details and versions -> Deactivate all versions -> Delete flow
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Formula-picklist-field-issue/index.html b/sf-deployment-assistant/Formula-picklist-field-issue/index.html new file mode 100644 index 000000000..191d27419 --- /dev/null +++ b/sf-deployment-assistant/Formula-picklist-field-issue/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Formula picklist field issue (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Formula picklist field issue

+

Detection

+
    +
  • String: Les champs de liste de sélection sont pris en charge uniquement dans certaines fonctions.
  • +
+

Resolution

+
You probably changed the type of a field that is used in a formula.
+Update the formula to use a field compliant with formulas.
+More details at https://help.salesforce.com/articleView?id=sf.tips_on_building_formulas.htm&type=5
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Insufficient-access-rights-on-cross-reference-id/index.html b/sf-deployment-assistant/Insufficient-access-rights-on-cross-reference-id/index.html new file mode 100644 index 000000000..538f55068 --- /dev/null +++ b/sf-deployment-assistant/Insufficient-access-rights-on-cross-reference-id/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Insufficient access rights on cross-reference id (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Insufficient access rights on cross-reference id

+

Detection

+
    +
  • RegExp: Error (.*) insufficient access rights on cross-reference id
  • +
+

Resolution

+
- If {1} is a Flow, it can not be deleted using deployments, please delete it manually in the target org using menu Setup -> Flows , context menu on {1} -> View details and versions -> Deactivate all versions -> Delete flow
+- If you changed a custom field from unique to not unique, you need to manually make the change in the target org
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Invalid-field-for-upsert/index.html b/sf-deployment-assistant/Invalid-field-for-upsert/index.html new file mode 100644 index 000000000..cf4be0a9e --- /dev/null +++ b/sf-deployment-assistant/Invalid-field-for-upsert/index.html @@ -0,0 +1,7623 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Invalid field for upsert - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +
+

title: "Invalid field for upsert (Deployment assistant)" +description: "How to solve Salesforce deployment error \"Error (.) Invalid field for upsert, must be an External Id custom or standard indexed field: (.) ((.*))\""

+
+ +

Invalid field for upsert

+

Detection

+
    +
  • RegExp: Error (.*) Invalid field for upsert, must be an External Id custom or standard indexed field: (.*) \((.*)\)
  • +
+

Resolution

+
You tried to use field {2} for an upsert call in {1}.
+- Is it declared as externalId ?
+- Is the customIndex source file present in the deployment ?
+- If it is declared as externalId and customIndex is present, you may have to go manually define the field as externalId in the target org
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Invalid-field-in-related-list/index.html b/sf-deployment-assistant/Invalid-field-in-related-list/index.html new file mode 100644 index 000000000..a3753fbea --- /dev/null +++ b/sf-deployment-assistant/Invalid-field-in-related-list/index.html @@ -0,0 +1,7630 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Invalid field in related list (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Invalid field in related list

+

Detection

+
    +
  • RegExp: Error (.*) Invalid field:(.*) in related list:(.*)
  • +
+

Resolution

+
Field {2} is unknown. You can:
+- Activate the related feature license or option to make {2} existing in target org
+- Update XML of {1} to remove reference to field {2} in the related list {3}
+- Update XML of {1} to remove the whole related list {3}
+Example of XML to remove:
+<relatedLists>
+  <fields>SOLUTION.ISSUE</fields>
+  <fields>SOLUTION.SOLUTION_NUMBER</fields>
+  <fields>SOLUTION.STATUS</fields>
+  <fields>CORE.USERS.ALIAS</fields>
+  <relatedList>RelatedSolutionList</relatedList>
+</relatedLists>
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Invalid-formula-grouping-context/index.html b/sf-deployment-assistant/Invalid-formula-grouping-context/index.html new file mode 100644 index 000000000..2db72c018 --- /dev/null +++ b/sf-deployment-assistant/Invalid-formula-grouping-context/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Invalid formula grouping context (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Invalid formula grouping context

+

Detection

+
    +
  • String: Invalid custom summary formula definition: You must select a grouping context to use any report summary function
  • +
+

Resolution

+
You need to update your Report definition. See workaround here -> https://salesforce.stackexchange.com/questions/294850/grouping-error-with-prevgroupval-function
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Invalid-report-type/index.html b/sf-deployment-assistant/Invalid-report-type/index.html new file mode 100644 index 000000000..d16a71597 --- /dev/null +++ b/sf-deployment-assistant/Invalid-report-type/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Invalid report type (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Invalid report type

+

Detection

+
    +
  • RegExp: Error (.*) invalid report type
  • +
+

Resolution

+
Report type is missing for report {1}
+- Open report {1} to se what report type is used
+- Retrieve the report type from an org and add it to the sfdx sources
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Invalid-scope-Mine--not-allowed/index.html b/sf-deployment-assistant/Invalid-scope-Mine--not-allowed/index.html new file mode 100644 index 000000000..c204c6a5d --- /dev/null +++ b/sf-deployment-assistant/Invalid-scope-Mine--not-allowed/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Invalid scope:Mine, not allowed (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Invalid scope:Mine, not allowed

+

Detection

+
    +
  • String: Invalid scope:Mine, not allowed
  • +
+

Resolution

+
Replace Mine by Everything in the list view SFDX source XML.
+Have a look at this command to manage that automatically :)
+https://sfdx-hardis.cloudity.com/hardis/org/fix/listviewmine/ 
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Invalid-type/index.html b/sf-deployment-assistant/Invalid-type/index.html new file mode 100644 index 000000000..871eec4ed --- /dev/null +++ b/sf-deployment-assistant/Invalid-type/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Invalid type - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +
+

title: "Invalid type (Deployment assistant)" +description: "How to solve Salesforce deployment error \"Error (.) Invalid type: (.) ((.*))\""

+
+ +

Invalid type

+

Detection

+
    +
  • RegExp: Error (.*) Invalid type: (.*) \((.*)\)
  • +
+

Resolution

+
Apex error in {1} with unknown type {2} at position {3}. If {2} is a class name, try to fix it, or maybe it is missing in the files or in package.xml !
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Mandatory-custom-field-can-not-be-in-a-profile-permission-set/index.html b/sf-deployment-assistant/Mandatory-custom-field-can-not-be-in-a-profile-permission-set/index.html new file mode 100644 index 000000000..bef7eb929 --- /dev/null +++ b/sf-deployment-assistant/Mandatory-custom-field-can-not-be-in-a-profile-permission-set/index.html @@ -0,0 +1,7625 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Mandatory custom field can not be in a profile/permission set (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Mandatory custom field can not be in a profile/permission set

+

Detection

+
    +
  • RegExp: Error (.*) You cannot deploy to a required field: (.*)
  • +
+

Resolution

+
- Search for {2} in source file XML of {1}, then remove the entries matching the results
+Example of element to delete:
+<fieldPermissions>
+  <editable>true</editable>
+  <field>{2}</field>
+  <readable>true</readable>
+</fieldPermissions>
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-Data-Category-Group/index.html b/sf-deployment-assistant/Missing-Data-Category-Group/index.html new file mode 100644 index 000000000..3918f10ee --- /dev/null +++ b/sf-deployment-assistant/Missing-Data-Category-Group/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing Data Category Group (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing Data Category Group

+

Detection

+
    +
  • RegExp: Error (.*) In field: DeveloperName - no DataCategoryGroup named (.*) found
  • +
+

Resolution

+
If Data Category Group {2} is not existing yet in target org, you might need to:
+- create it manually in target org before deployment
+- comment DataCategoryGroup in {1} XML
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-Feature-Work-Com/index.html b/sf-deployment-assistant/Missing-Feature-Work-Com/index.html new file mode 100644 index 000000000..a5a7be419 --- /dev/null +++ b/sf-deployment-assistant/Missing-Feature-Work-Com/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing Feature Work.Com (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing Feature Work.Com

+

Detection

+
    +
  • String: WorkBadgeDefinition
  • +
+

Resolution

+
Work.com feature must be activated in the target org.
+- Org & Scratch: https://developer.salesforce.com/docs/atlas.en-us.workdotcom_dev_guide.meta/workdotcom_dev_guide/wdc_cc_setup_dev_org.htm
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-Quick-Action/index.html b/sf-deployment-assistant/Missing-Quick-Action/index.html new file mode 100644 index 000000000..da454f841 --- /dev/null +++ b/sf-deployment-assistant/Missing-Quick-Action/index.html @@ -0,0 +1,7626 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing Quick Action (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing Quick Action

+

Detection

+
    +
  • RegExp: Error (.*) In field: QuickAction - no QuickAction named (.*) found
  • +
+

Resolution

+
QuickAction {2} referred in {1} is unknown. You can either:
+- Make sure your QuickAction {2} is present in source files and in package.xml
+- If {2} is a standard QuickAction, activate related feature in target org
+- Solve other errors that could impact QuickAction {2}
+- Remove QuickAction {2} in the source XML of {1}. Example of XML to remove below:
+<quickActionListItems>
+  <quickActionName>FeedItem.RypplePost</quickActionName>
+</quickActionListItems>
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-Sales-Team/index.html b/sf-deployment-assistant/Missing-Sales-Team/index.html new file mode 100644 index 000000000..e27d6c528 --- /dev/null +++ b/sf-deployment-assistant/Missing-Sales-Team/index.html @@ -0,0 +1,7625 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing Sales Team (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing Sales Team

+

Detection

+
    +
  • String: related list:RelatedAccountSalesTeam
  • +
+

Resolution

+
Account Teams must be activated in the target org.
+- Org: Setup -> Account Teams -> Enable
+- Scratch org setting:
+"accountSettings": {
+  "enableAccountTeams": true
+}
+}
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-e-mail-template/index.html b/sf-deployment-assistant/Missing-e-mail-template/index.html new file mode 100644 index 000000000..63424f0be --- /dev/null +++ b/sf-deployment-assistant/Missing-e-mail-template/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing e-mail template (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing e-mail template

+

Detection

+
    +
  • RegExp: In field: template - no EmailTemplate named (.*) found
  • +
+

Resolution

+
An email template should be present in the sources. To retrieve it, you can run:
+sf project retrieve start -m EmailTemplate:{1} -o YOUR_ORG_USERNAME
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-feature-Chatter-Collaboration-Group/index.html b/sf-deployment-assistant/Missing-feature-Chatter-Collaboration-Group/index.html new file mode 100644 index 000000000..d5a01cf91 --- /dev/null +++ b/sf-deployment-assistant/Missing-feature-Chatter-Collaboration-Group/index.html @@ -0,0 +1,7624 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing feature Chatter Collaboration Group (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing feature Chatter Collaboration Group

+

Detection

+
    +
  • String: CollaborationGroup
  • +
+

Resolution

+
Quotes must be activated in the target org.
+- Org: Setup -> Chatter settings -> Allow Records in Groups
+- Scratch org setting:
+"chatterSettings": {
+  "allowRecordsInChatterGroup": true
+},
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-feature-ContactToMultipleAccounts/index.html b/sf-deployment-assistant/Missing-feature-ContactToMultipleAccounts/index.html new file mode 100644 index 000000000..16cdb7df2 --- /dev/null +++ b/sf-deployment-assistant/Missing-feature-ContactToMultipleAccounts/index.html @@ -0,0 +1,7623 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing feature ContactToMultipleAccounts (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing feature ContactToMultipleAccounts

+

Detection

+
    +
  • String: no CustomObject named AccountContactRelation found
  • +
  • String: Invalid field:ACCOUNT.NAME in related list:RelatedContactAccountRelationList
  • +
+

Resolution

+
Contacts to multiple accounts be activated in the target org.
+- Help: https://help.salesforce.com/articleView?id=sf.shared_contacts_set_up.htm&type=5
+- Scratch org setting:
+"features": ["ContactsToMultipleAccounts"]
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-feature-Enhanced-notes/index.html b/sf-deployment-assistant/Missing-feature-Enhanced-notes/index.html new file mode 100644 index 000000000..b6017db86 --- /dev/null +++ b/sf-deployment-assistant/Missing-feature-Enhanced-notes/index.html @@ -0,0 +1,7624 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing feature Enhanced notes (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing feature Enhanced notes

+

Detection

+
    +
  • String: FeedItem.ContentNote
  • +
+

Resolution

+
Enhanced Notes must be activated in the target org.
+- Org: Setup -> Notes settings -> Enable Notes
+- Scratch org setting:
+"enhancedNotesSettings": {
+  "enableEnhancedNotes": true
+},
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-feature-Ideas-notes/index.html b/sf-deployment-assistant/Missing-feature-Ideas-notes/index.html new file mode 100644 index 000000000..e407cbdce --- /dev/null +++ b/sf-deployment-assistant/Missing-feature-Ideas-notes/index.html @@ -0,0 +1,7624 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing feature Ideas notes (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing feature Ideas notes

+

Detection

+
    +
  • String: Idea.InternalIdeasIdeaRecordType
  • +
+

Resolution

+
Ideas must be activated in the target org.
+- Org: https://help.salesforce.com/articleView?id=networks_enable_ideas.htm&type=0
+- Scratch org setting:
+"ideasSettings": {
+  "enableIdeas": true
+}
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-feature-Live-Agent/index.html b/sf-deployment-assistant/Missing-feature-Live-Agent/index.html new file mode 100644 index 000000000..9be3ed116 --- /dev/null +++ b/sf-deployment-assistant/Missing-feature-Live-Agent/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing feature Live Agent (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing feature Live Agent

+

Detection

+
    +
  • String: FeedItem.ContentNote
  • +
+

Resolution

+
Live Agent must be activated in the target org.
+- Org: Setup -> Live Agent Settings -> Enable Live Agent
+- Scratch org feature: LiveAgent
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-feature-Opportunity-Teams/index.html b/sf-deployment-assistant/Missing-feature-Opportunity-Teams/index.html new file mode 100644 index 000000000..c65ad29c5 --- /dev/null +++ b/sf-deployment-assistant/Missing-feature-Opportunity-Teams/index.html @@ -0,0 +1,7624 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing feature Opportunity Teams (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing feature Opportunity Teams

+

Detection

+
    +
  • String: OpportunityTeam
  • +
+

Resolution

+
Opportunity Teams must be activated in the target org.
+- Org: Setup -> Opportunity Team Settings -> Enable Team Selling
+- Scratch org:
+"opportunitySettings": {
+  "enableOpportunityTeam": true
+}
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-feature-Product-Request/index.html b/sf-deployment-assistant/Missing-feature-Product-Request/index.html new file mode 100644 index 000000000..cd754fe1c --- /dev/null +++ b/sf-deployment-assistant/Missing-feature-Product-Request/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing feature Product Request (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing feature Product Request

+

Detection

+
    +
  • String: ProductRequest
  • +
+

Resolution

+
ProductRequest object is not available in the target org.
+Maybe you would like to clean its references within Profiles / PS using the following command ?
+sf hardis:project:clean:references , then select "ProductRequest references"
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-feature-Social-Customer-Service/index.html b/sf-deployment-assistant/Missing-feature-Social-Customer-Service/index.html new file mode 100644 index 000000000..9ee0977bf --- /dev/null +++ b/sf-deployment-assistant/Missing-feature-Social-Customer-Service/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing feature Social Customer Service (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing feature Social Customer Service

+

Detection

+
    +
  • String: SocialPersona.AreWeFollowing
  • +
+

Resolution

+
Social Custom Service must be activated in the target org.
+- Org: Setup -> https://help.salesforce.com/articleView?id=sf.social_customer_service_setup_enable.htm&type=5
+- Scratch org feature: SocialCustomerService
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-feature-Translation-Workbench/index.html b/sf-deployment-assistant/Missing-feature-Translation-Workbench/index.html new file mode 100644 index 000000000..d13181898 --- /dev/null +++ b/sf-deployment-assistant/Missing-feature-Translation-Workbench/index.html @@ -0,0 +1,7625 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing feature Translation Workbench (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing feature Translation Workbench

+

Detection

+
    +
  • RegExp: report-meta.xml(.*)filterlanguage
  • +
+

Resolution

+
Translation workbench must be activated in the target org.
+- Org: Setup -> https://help.salesforce.com/articleView?id=sf.customize_wbench.htm&type=5
+- Scratch org:
+"languageSettings": {
+  "enableTranslationWorkbench":  true,
+  "enableEndUserLanguages": true
+}
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-field-MiddleName/index.html b/sf-deployment-assistant/Missing-field-MiddleName/index.html new file mode 100644 index 000000000..0164580d3 --- /dev/null +++ b/sf-deployment-assistant/Missing-field-MiddleName/index.html @@ -0,0 +1,7625 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing field MiddleName (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing field MiddleName

+

Detection

+
    +
  • String: field MiddleName
  • +
  • String: Variable does not exist: MiddleName
  • +
+

Resolution

+
MiddleNames must be activated in the target org.
+- Help: https://help.salesforce.com/articleView?id=000332623&type=1&mode=1
+- Scratch org setting:
+"nameSettings": {
+  "enableMiddleName": true
+}
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-field-Suffix/index.html b/sf-deployment-assistant/Missing-field-Suffix/index.html new file mode 100644 index 000000000..c482c1aa6 --- /dev/null +++ b/sf-deployment-assistant/Missing-field-Suffix/index.html @@ -0,0 +1,7624 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing field Suffix (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing field Suffix

+

Detection

+
    +
  • String: field Suffix
  • +
+

Resolution

+
Suffix must be activated in the target org.
+- Help: https://help.salesforce.com/articleView?id=000332623&type=1&mode=1
+- Scratch org setting:
+"nameSettings": {
+  "enableNameSuffix": true
+},
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-field-SyncedQuoteId/index.html b/sf-deployment-assistant/Missing-field-SyncedQuoteId/index.html new file mode 100644 index 000000000..ec195a7da --- /dev/null +++ b/sf-deployment-assistant/Missing-field-SyncedQuoteId/index.html @@ -0,0 +1,7626 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing field SyncedQuoteId (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing field SyncedQuoteId

+

Detection

+
    +
  • String: field SyncedQuoteId
  • +
  • String: Error force-app/main/default/objects/Quote/Quote.object-meta.xml
  • +
  • String: Error force-app/main/default/objects/Opportunity/fields/SyncedQuoteId.field-meta.xml
  • +
+

Resolution

+
Quotes must be activated in the target org.
+- Help: https://help.salesforce.com/articleView?id=sf.quotes_enable.htm&type=5
+- Scratch org setting:
+"quoteSettings": {
+  "enableQuote": true
+}
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-multi-currency-field/index.html b/sf-deployment-assistant/Missing-multi-currency-field/index.html new file mode 100644 index 000000000..cdf4d0281 --- /dev/null +++ b/sf-deployment-assistant/Missing-multi-currency-field/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing multi-currency field (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing multi-currency field

+

Detection

+
    +
  • RegExp: A reference to a custom field (.*)CurrencyIsoCode
  • +
+

Resolution

+
You probably need to activate MultiCurrency (from Setup -> Company information)
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-object-referenced-in-package-xml/index.html b/sf-deployment-assistant/Missing-object-referenced-in-package-xml/index.html new file mode 100644 index 000000000..0133675b7 --- /dev/null +++ b/sf-deployment-assistant/Missing-object-referenced-in-package-xml/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing object referenced in package.xml (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing object referenced in package.xml

+

Detection

+
    +
  • RegExp: An object (.*) of type (.*) was named in package.xml, but was not found in zipped directory
  • +
+

Resolution

+
You can either:
+- Update the package.xml to remove the reference to the missing {2} {1}
+- Add the missing {2} {1} in your project source files
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-profile-default-application/index.html b/sf-deployment-assistant/Missing-profile-default-application/index.html new file mode 100644 index 000000000..49448b5b6 --- /dev/null +++ b/sf-deployment-assistant/Missing-profile-default-application/index.html @@ -0,0 +1,7627 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing profile default application (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing profile default application

+

Detection

+
    +
  • String: You can't remove the only default app from the profile.
  • +
+

Resolution

+
You must have a default application for a profile. You can:
+ - Update it in UI
+ - Update the XML of the profile to set "true" in the <default> tag of one of the applicationVisibilities item.
+ Ex:
+ <applicationVisibilities>
+    <application>standard__LightningSales</application>
+    <default>true</default>
+    <visible>true</visible>
+</applicationVisibilities>
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Missing-report/index.html b/sf-deployment-assistant/Missing-report/index.html new file mode 100644 index 000000000..8e59c0e0f --- /dev/null +++ b/sf-deployment-assistant/Missing-report/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Missing report (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Missing report

+

Detection

+
    +
  • RegExp: Error (.*) The (.*) report chart has a problem with the "reportName" field
  • +
+

Resolution

+
{1} is referring to unknown report {2}. To retrieve it, you can run:
+- sf project retrieve start -m Report:{2} -o YOUR_ORG_USERNAME
+- If it fails, looks for the report folder and add it before report name to the retrieve command (ex: MYFOLDER/MYREPORTNAME)
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Network-issue/index.html b/sf-deployment-assistant/Network-issue/index.html new file mode 100644 index 000000000..989be55dc --- /dev/null +++ b/sf-deployment-assistant/Network-issue/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Network issue (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Network issue

+

Detection

+
    +
  • String: ECONNABORTED
  • +
  • String: ECONNRESET
  • +
+

Resolution

+
The network connection has been aborted, this is a purely technical issue.
+Try again, and if you still see errors, check the status of Salesforce instance on https://status.salesforce.com
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Not-available-for-deploy-for-this-organization/index.html b/sf-deployment-assistant/Not-available-for-deploy-for-this-organization/index.html new file mode 100644 index 000000000..bcd197515 --- /dev/null +++ b/sf-deployment-assistant/Not-available-for-deploy-for-this-organization/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Not available for deploy for this organization (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Not available for deploy for this organization

+

Detection

+
    +
  • RegExp: Error (.*) Not available for deploy for this organization
  • +
+

Resolution

+
The user you use for deployments probably lacks of the rights (Profiles, Permission sets...) to manage {1}.
+- Assign the deployment user to the good Permission Sets, or modify its profile rights, then try again
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Not-valid-sharing-model/index.html b/sf-deployment-assistant/Not-valid-sharing-model/index.html new file mode 100644 index 000000000..1d252aab3 --- /dev/null +++ b/sf-deployment-assistant/Not-valid-sharing-model/index.html @@ -0,0 +1,7622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Not valid sharing model (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Not valid sharing model

+

Detection

+
    +
  • RegExp: Error (.*) (.*) is not a valid sharing model for (.*) when (.*) sharing model is (.*)
  • +
+

Resolution

+
It seems that Sharing Models of {1} and {4} are not compatible in target org.
+- Use compatible sharing models between {1} and {4} by updating Sharing model of {1} or {4}
+- Make sure that sfdx sources {1}.object-meta.xml and {4}.object-meta.xml and in the files, and that {1} and {4} are in package.xml in CustomObject block
+- You may directly update sharingModel in XML. For example, replace <sharingModel>ReadWrite</sharingModel> by <sharingModel>Private</sharingModel> in {3}.object-meta.xml
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Objects-rights-on-a-role-is-below-org-default/index.html b/sf-deployment-assistant/Objects-rights-on-a-role-is-below-org-default/index.html new file mode 100644 index 000000000..8fa68dc83 --- /dev/null +++ b/sf-deployment-assistant/Objects-rights-on-a-role-is-below-org-default/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Objects rights on a role is below org default (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Objects rights on a role is below org default

+

Detection

+
    +
  • String: access level below organization default
  • +
+

Resolution

+
Your org wide settings default must be lower than the level defined in roles:
+- If you are in a scratch org, it can be fixable using "objectProperties" in project-scratch-def.json (see "Set Object-Level Sharing Settings" paragraph in page https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_scratch_orgs_def_file.htm)
+- If you are in a sandbox/dev/prod org, you need to update default org wide settings before deployment. See https://www.sfdcpoint.com/salesforce/organization-wide-defaults-owd-in-salesforce/
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Picklist-sharing-is-not-supported/index.html b/sf-deployment-assistant/Picklist-sharing-is-not-supported/index.html new file mode 100644 index 000000000..c02977dab --- /dev/null +++ b/sf-deployment-assistant/Picklist-sharing-is-not-supported/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Picklist sharing is not supported (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Picklist sharing is not supported

+

Detection

+
    +
  • String: Picklist sharing is not supported
  • +
+

Resolution

+
You probably changed the type of a field.
+Go manually make the change in the target org, so the deployment will pass
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Picklist-value-not-found/index.html b/sf-deployment-assistant/Picklist-value-not-found/index.html new file mode 100644 index 000000000..c044f4520 --- /dev/null +++ b/sf-deployment-assistant/Picklist-value-not-found/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Picklist value not found (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Picklist value not found

+

Detection

+
    +
  • RegExp: Picklist value: (.*) in picklist: (.*) not found
  • +
+

Resolution

+
Sources have references to value {1} of picklist {2}
+- If picklist {2} is standard, add the picklist to sfdx sources by using "sf project retrieve start -m StandardValueSet:{2}", then save again
+- Else, perform a search in all code of {1}, then remove XML tags referring to {1} (for example in record types metadatas)
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Please-choose-a-different-name/index.html b/sf-deployment-assistant/Please-choose-a-different-name/index.html new file mode 100644 index 000000000..3b1ee8d5f --- /dev/null +++ b/sf-deployment-assistant/Please-choose-a-different-name/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Please choose a different name (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Please choose a different name

+

Detection

+
    +
  • RegExp: Error (.*) This (.*) already exists or has been previously used(.*)Please choose a different name.
  • +
+

Resolution

+
- Rename {1} in the target org, then try again the deployment. if it succeeds, delete the renamed item.
+- or Delete {1} in the target org, then try again the deployment
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Record-Type-not-found/index.html b/sf-deployment-assistant/Record-Type-not-found/index.html new file mode 100644 index 000000000..ab1a56471 --- /dev/null +++ b/sf-deployment-assistant/Record-Type-not-found/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Record Type not found (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Record Type not found

+

Detection

+
    +
  • RegExp: Error (.*) In field: recordType - no RecordType named (.*) found
  • +
+

Resolution

+
An unknown record type {2} is referenced in {1}
+- If record type {2} is not supposed to exist, perform a search in all files of {1}, then remove matching XML elements referring to this record type
+- If record type {2} is supposed to exist, you may have to create it manually in the target org to make the deployment pass
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Send-email-is-disabled/index.html b/sf-deployment-assistant/Send-email-is-disabled/index.html new file mode 100644 index 000000000..661123746 --- /dev/null +++ b/sf-deployment-assistant/Send-email-is-disabled/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Send email is disabled (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Send email is disabled

+

Detection

+
    +
  • String: Send Email is disabled or activities are not allowed
  • +
  • String: Unknown user permission: SendExternalEmailAvailable
  • +
+

Resolution

+
Go to Email -> Deliverability -> Select value "All emails"
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Sharing-recalculation-lock/index.html b/sf-deployment-assistant/Sharing-recalculation-lock/index.html new file mode 100644 index 000000000..3841e8e2b --- /dev/null +++ b/sf-deployment-assistant/Sharing-recalculation-lock/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Sharing recalculation lock (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Sharing recalculation lock

+

Detection

+
    +
  • String: because it interferes with another operation already in progress
  • +
  • String: Le calcul de partage demandé ne peut être traité maintenant car il interfère avec une autre opération en cours
  • +
+

Resolution

+
If you changed a field from MasterDetail to Lookup, you must do it manually in the target org before being able to deploy
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Sort-order-must-be-in-sequential-order/index.html b/sf-deployment-assistant/Sort-order-must-be-in-sequential-order/index.html new file mode 100644 index 000000000..c6a90d4be --- /dev/null +++ b/sf-deployment-assistant/Sort-order-must-be-in-sequential-order/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Sort order must be in sequential order (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Sort order must be in sequential order

+

Detection

+
    +
  • RegExp: Error (.*) SortOrder must be in sequential order from
  • +
+

Resolution

+
You probably have a default DuplicateRule in the target org. Retrieve it from target org, or delete it manually in target org, so you can deploy.
+Ref: https://developer.salesforce.com/forums/?id=9060G000000I6SoQAK
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Tableau-CRM---Wave-digest-error/index.html b/sf-deployment-assistant/Tableau-CRM---Wave-digest-error/index.html new file mode 100644 index 000000000..0d40bebf4 --- /dev/null +++ b/sf-deployment-assistant/Tableau-CRM---Wave-digest-error/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Tableau CRM / Wave digest error (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Tableau CRM / Wave digest error

+

Detection

+
    +
  • String: Fix the sfdcDigest node errors and then upload the file again
  • +
+

Resolution

+
Go to the target org, open profile "Analytics Cloud Integration User" and add READ rights to the missing object fields 
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Test-classes-with-0--coverage/index.html b/sf-deployment-assistant/Test-classes-with-0--coverage/index.html new file mode 100644 index 000000000..9f5dd1c2e --- /dev/null +++ b/sf-deployment-assistant/Test-classes-with-0--coverage/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Test classes with 0% coverage (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Test classes with 0% coverage

+

Detection

+
    +
  • RegExp: 0%
  • +
+

Resolution

+
Please make sure that none of the test classes are 0% covered
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Unknown-user-permission--CreateAuditFields/index.html b/sf-deployment-assistant/Unknown-user-permission--CreateAuditFields/index.html new file mode 100644 index 000000000..00a87ab24 --- /dev/null +++ b/sf-deployment-assistant/Unknown-user-permission--CreateAuditFields/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Unknown user permission: CreateAuditFields (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Unknown user permission: CreateAuditFields

+

Detection

+
    +
  • String: Unknown user permission: CreateAuditFields
  • +
+

Resolution

+
You need to enable the "Create audit field" permission in the target org
+Please check https://help.salesforce.com/articleView?id=000334139&type=1&mode=1
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Unknown-user-permission--FieldServiceAccess/index.html b/sf-deployment-assistant/Unknown-user-permission--FieldServiceAccess/index.html new file mode 100644 index 000000000..fb6c2bb9d --- /dev/null +++ b/sf-deployment-assistant/Unknown-user-permission--FieldServiceAccess/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Unknown user permission: FieldServiceAccess (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Unknown user permission: FieldServiceAccess

+

Detection

+
    +
  • String: Unknown user permission: FieldServiceAccess
  • +
+

Resolution

+
You need to enable the "Field Service Access" permission in the target org
+Please check https://help.salesforce.com/articleView?id=sf.fs_enable.htm&type=5
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Unknown-user-permission/index.html b/sf-deployment-assistant/Unknown-user-permission/index.html new file mode 100644 index 000000000..f1af2d24f --- /dev/null +++ b/sf-deployment-assistant/Unknown-user-permission/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Unknown user permission (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Unknown user permission

+

Detection

+
    +
  • String: Unknown user permission:
  • +
+

Resolution

+
You can:
+- enable the related permission in the target org
+- or remove references to the permission in source XML files (Probably a Profile or a Permission set)
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Unsupported-sharing-configuration/index.html b/sf-deployment-assistant/Unsupported-sharing-configuration/index.html new file mode 100644 index 000000000..b709f0f96 --- /dev/null +++ b/sf-deployment-assistant/Unsupported-sharing-configuration/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported sharing configuration (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Unsupported sharing configuration

+

Detection

+
    +
  • RegExp: not supported for (.*) since it's org wide default is
  • +
+

Resolution

+
Consistency error between {1} sharing settings and {1} object configuration
+Please check https://salesforce.stackexchange.com/questions/260923/sfdx-deploying-contact-sharing-rules-on-a-fresh-deployment
+If you already did that, please try again to run the job
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Variable-does-not-exist/index.html b/sf-deployment-assistant/Variable-does-not-exist/index.html new file mode 100644 index 000000000..00102c854 --- /dev/null +++ b/sf-deployment-assistant/Variable-does-not-exist/index.html @@ -0,0 +1,7620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Variable does not exist - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +
+

title: "Variable does not exist (Deployment assistant)" +description: "How to solve Salesforce deployment error \"Error (.) Variable does not exist: (.) ((.*))\""

+
+ +

Variable does not exist

+

Detection

+
    +
  • RegExp: Error (.*) Variable does not exist: (.*) \((.*)\)
  • +
+

Resolution

+
Apex error in {1} with unknown variable {2} at position {3}. If {2} is a class name, try to fix it, or maybe it is missing in the files or in package.xml !
+
+ + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/Visibility-is-not-allowed-for-type/index.html b/sf-deployment-assistant/Visibility-is-not-allowed-for-type/index.html new file mode 100644 index 000000000..818fa8db5 --- /dev/null +++ b/sf-deployment-assistant/Visibility-is-not-allowed-for-type/index.html @@ -0,0 +1,7619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Visibility is not allowed for type (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Visibility is not allowed for type

+

Detection

+
    +
  • RegExp: Error (.*) set the visibility for a (.*) to Protected unless you are in a developer
  • +
+

Resolution

+
Update the visibility of {1} to "Public"
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/XML-item-appears-more-than-once/index.html b/sf-deployment-assistant/XML-item-appears-more-than-once/index.html new file mode 100644 index 000000000..d74253c52 --- /dev/null +++ b/sf-deployment-assistant/XML-item-appears-more-than-once/index.html @@ -0,0 +1,7621 @@ + + + + + + + + + + + + + + + + + + + + + + + + + XML item appears more than once (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

XML item appears more than once

+

Detection

+
    +
  • RegExp: Error (.*) Field:(.*), value:(.*) appears more than once
  • +
+

Resolution

+
You probably made an error while merging conflicts
+Look for {3} in the XML of {1}
+If you see two {2} XML blocks with {3}, please decide which one you keep and remove the other one
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf-deployment-assistant/sharing-operation-already-in-progress/index.html b/sf-deployment-assistant/sharing-operation-already-in-progress/index.html new file mode 100644 index 000000000..8fc92bd7a --- /dev/null +++ b/sf-deployment-assistant/sharing-operation-already-in-progress/index.html @@ -0,0 +1,7622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + sharing operation already in progress (Deployment assistant) - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

sharing operation already in progress

+

Detection

+
    +
  • String: sharing operation already in progress
  • +
+

Resolution

+
You can not deploy multiple SharingRules at the same time. You can either:
+- Remove SharingOwnerRules and SharingRule from package.xml (so it becomes a manual operation)
+- Use sf hardis:work:save to generate a deploymentPlan in .sfdx-hardis.json,
+- If you are trying to create a scratch org, add DeferSharingCalc in features in project-scratch-def.json
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ +
+ + + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sfdx-hardis-config-file/index.html b/sfdx-hardis-config-file/index.html new file mode 100644 index 000000000..5479410b9 --- /dev/null +++ b/sfdx-hardis-config-file/index.html @@ -0,0 +1,7692 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .sfdx-hardis.yml config file - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Configuration reference

+ + + +

sfdx-hardis projects are like any other sfdx projects, but with an additional configuration stored in a .sfdx-hardis.yml config file

+

Many of these properties are automatically set by CI/CD setup and maintenance operations.

+

You can see the list of all configuration properties.

+

Here is an example of a .sfdx-hardis.yml config file:

+
projectName: MyClient
+devHubAlias: DevHub_MyClient
+developmentBranch: integration
+allowedOrgTypes:
+  - sandbox
+availableTargetBranches:
+  - develop
+  - preprod
+autoCleanTypes:
+  - destructivechanges
+  - datadotcom
+  - minimizeProfiles
+  - listViewsMine
+autoRemoveUserPermissions:
+  - EnableCommunityAppLauncher
+  - FieldServiceAccess
+  - OmnichannelInventorySync
+  - SendExternalEmailAvailable
+  - UseOmnichannelInventoryAPIs
+  - ViewDataLeakageEvents
+  - ViewMLModels
+  - ViewPlatformEvents
+  - WorkCalibrationUser
+autoRetrieveWhenPull:
+  - CustomApplication:MyClient
+  - CustomApplication:MyClientConnectApplication
+  - CustomApplication:MyOtherApplication
+  - CustomMetadata
+devHubUsername: nicolas.vuillamy@ext.myclient.com
+installPackagesDuringCheckDeploy: true
+installedPackages:
+  - Id: 0A37Z000000AtDYSA0
+    SubscriberPackageId: 033i0000000LVMYAA4
+    SubscriberPackageName: Marketing Cloud
+    SubscriberPackageNamespace: et4ae5
+    SubscriberPackageVersionId: 04t6S000001UjutQAC
+    SubscriberPackageVersionName: Marketing Cloud
+    SubscriberPackageVersionNumber: 238.3.0.2
+    installOnScratchOrgs: true
+    installDuringDeployments: true
+  - Id: 0A35r0000009F9CCAU
+    SubscriberPackageId: 033b0000000Pf2AAAS
+    SubscriberPackageName: Declarative Lookup Rollup Summaries Tool
+    SubscriberPackageNamespace: dlrs
+    SubscriberPackageVersionId: 04t5p000001BmLvAAK
+    SubscriberPackageVersionName: Release
+    SubscriberPackageVersionNumber: 2.15.0.9
+    installOnScratchOrgs: true
+    installDuringDeployments: true
+initPermissionSets:
+  - AdminDefault
+  - MarketingCloudConnectedApp
+  - ApiUserPS
+listViewsToSetToMine:
+  - force-app/main/default/objects/Operation__c/listViews/MyCurrentOperations.listView-meta.xml
+  - force-app/main/default/objects/Operation__c/listViews/MyFinalizedOperations.listView-meta.xml
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sfdx-hardis-help/index.html b/sfdx-hardis-help/index.html new file mode 100644 index 000000000..55385cc24 --- /dev/null +++ b/sfdx-hardis-help/index.html @@ -0,0 +1,7633 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + sfdx-hardis help - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Help

+ + + +

You have a question or need assistance ?

+

Feel free to contact us 🙂 :)

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 000000000..5d4037573 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,1159 @@ + + + + https://sfdx-hardis.cloudity.com/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/CHANGELOG/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/cloudity-consulting-partner/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/commands/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/license/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ai-setup/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-clone-repository/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-config-cleaning/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-config-delta-deployment/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-config-home/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-config-overwrite/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-conga/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-create-new-task/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-deploy-major-branches/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-handle-merge-request-results/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-home/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-hotfixes/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-merge-request-gitlab/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-packaging/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-publish-task/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-pull-request-azure/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-pull-request-github/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-release-home/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-retrieve/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-activate-org/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-auth-azure/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-auth-bitbucket/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-auth-github/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-auth-gitlab/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-auth-jenkins/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-auth/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-existing-org/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-git/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-home/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-init-project/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-api/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-azure-boards/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-azure/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-bitbucket/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-email/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-generic-ticketing/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-github/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-gitlab/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-jira/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-ms-teams/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integration-slack/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-integrations-home/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-setup-merge-request/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-solve-deployment-errors/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-solve-megalinter-errors/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-use-home/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-use-install/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-validate-merge-request/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-work-on-task-configuration/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-work-on-task-development/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-work-on-task-install-packages/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-work-on-task-open-org/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-work-on-task-profiles/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-ci-cd-work-on-task/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-deployment-assistant-error-list/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-deployment-assistant-home/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-deployment-assistant-setup/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-apex-tests/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-config-azure/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-config-bitbucket/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-config-github/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-config-gitlab/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-config-home/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-deprecated-api-calls/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-home/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-inactive-metadata/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-inactive-users/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-metadata-backup/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-missing-access/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-missing-metadata-attributes/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-org-limits/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-quality-checks/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-release-updates/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-suspect-audit-trail/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-unused-apex-classes/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-unused-connected-apps/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-unused-licenses/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-monitoring-unused-metadata/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/salesforce-project-documentation/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sfdx-hardis-config-file/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sfdx-hardis-help/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/special-thanks/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/auth/login/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/cache/clear/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/config/get/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/deploy/quick/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/deploy/start/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/deploy/validate/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/doc/flow2markdown/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/doc/mkdocs-to-salesforce/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/doc/packagexml2markdown/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/doc/project2markdown/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/doc/extract/permsetgroups/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/doc/plugin/generate/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/git/pull-requests/extract/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/lint/access/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/lint/metadatastatus/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/lint/missingattributes/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/lint/unusedmetadatas/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/mdapi/deploy/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/misc/purge-references/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/misc/toml2csv/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/connect/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/create/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/multi-org-query/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/select/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/community/update/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/configure/data/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/configure/files/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/configure/monitoring/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/data/delete/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/data/export/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/data/import/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/diagnose/audittrail/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/diagnose/instanceupgrade/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/diagnose/legacyapi/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/diagnose/licenses/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/diagnose/releaseupdates/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unused-apex-classes/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unused-connected-apps/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedlicenses/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/diagnose/unusedusers/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/files/export/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/files/import/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/fix/listviewmine/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/generate/packagexmlfull/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/monitor/all/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/monitor/backup/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/monitor/limits/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/purge/apexlog/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/purge/flow/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/retrieve/packageconfig/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/retrieve/sources/analytics/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/retrieve/sources/dx/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/retrieve/sources/dx2/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/retrieve/sources/metadata/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/retrieve/sources/retrofit/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/test/apex/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/user/activateinvalid/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/user/freeze/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/org/user/unfreeze/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/package/create/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/package/install/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/package/mergexml/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/package/version/create/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/package/version/list/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/package/version/promote/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/packagexml/append/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/packagexml/remove/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/create/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/lint/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/audit/apiversion/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/audit/callincallout/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/audit/duplicatefiles/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/audit/remotesites/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/emptyitems/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/filter-xml-content/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/flowpositions/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/hiddenitems/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/listviews/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/manageditems/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/minimizeprofiles/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/orgmissingitems/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/references/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/retrievefolders/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/sensitive-metadatas/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/standarditems/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/systemdebug/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/clean/xml/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/configure/auth/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/convert/profilestopermsets/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/deploy/notify/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/deploy/quick/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/deploy/simulate/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/deploy/smart/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/deploy/start/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/deploy/validate/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/deploy/sources/dx/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/deploy/sources/metadata/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/fix/profiletabs/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/fix/v53flexipages/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/generate/flow-git-diff/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/generate/gitdelta/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/project/metadata/findduplicates/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/scratch/create/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/scratch/delete/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/scratch/pull/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/scratch/push/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/scratch/pool/create/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/scratch/pool/localauth/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/scratch/pool/refresh/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/scratch/pool/reset/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/scratch/pool/view/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/source/deploy/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/source/push/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/source/retrieve/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/work/new/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/work/refresh/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/work/resetselection/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/work/save/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hardis/work/ws/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/hello/world/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/A-sharing-rule-may-be-useless/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/API-Version-error/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Allow-deployment-with-pending-Apex-Jobs/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Async-exception-in-test-class/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/CRM-Analytics--A-Recipe-must-specify-a-DataFlow/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Campaign-can-not-be-updated/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Can-not-change-field-type-to-a-formula-field/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Can-not-change-field-type-with-picklist/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Can-not-change-type-due-to-existing-data/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Can-not-delete-custom-field/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Can-not-delete-record-type/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Can-not-find-folder/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Can-not-find-user--2-/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Can-not-find-user/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Can-not-test-item-deployment-in-simulation-mode/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Cannot-update-a-field-to-a-Summary-from-something-else/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Change-Matching-Rule/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Condition-missing-reference/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Couldn-t-retrieve-or-load-information-on-the-field/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Custom-field-not-found/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Custom-metadata-entry-not-found/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Custom-object-not-found/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Dependent-class-is-invalid-and-needs-recompilation/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Duplicate-label/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Duplicate-value-Platform-Action-Id-List/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Empty-source-items/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Enable-CRM-Analytics/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Error-parsing-file/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Expired-Access---Refresh-Token/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Field-not-available-for-element/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Flow-must-be-deleted-manually/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Formula-picklist-field-issue/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Insufficient-access-rights-on-cross-reference-id/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Invalid-field-for-upsert/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Invalid-field-in-related-list/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Invalid-formula-grouping-context/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Invalid-report-type/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Invalid-scope-Mine--not-allowed/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Invalid-type/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Mandatory-custom-field-can-not-be-in-a-profile-permission-set/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-Data-Category-Group/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-Feature-Work-Com/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-Quick-Action/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-Sales-Team/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-e-mail-template/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-feature-Chatter-Collaboration-Group/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-feature-ContactToMultipleAccounts/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-feature-Enhanced-notes/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-feature-Ideas-notes/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-feature-Live-Agent/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-feature-Opportunity-Teams/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-feature-Product-Request/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-feature-Social-Customer-Service/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-feature-Translation-Workbench/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-field-MiddleName/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-field-Suffix/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-field-SyncedQuoteId/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-multi-currency-field/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-object-referenced-in-package-xml/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-profile-default-application/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Missing-report/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Network-issue/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Not-available-for-deploy-for-this-organization/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Not-valid-sharing-model/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Objects-rights-on-a-role-is-below-org-default/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Picklist-sharing-is-not-supported/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Picklist-value-not-found/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Please-choose-a-different-name/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Record-Type-not-found/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Send-email-is-disabled/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Sharing-recalculation-lock/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Sort-order-must-be-in-sequential-order/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Tableau-CRM---Wave-digest-error/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Test-classes-with-0--coverage/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Unknown-user-permission--CreateAuditFields/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Unknown-user-permission--FieldServiceAccess/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Unknown-user-permission/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Unsupported-sharing-configuration/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Variable-does-not-exist/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/Visibility-is-not-allowed-for-type/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/XML-item-appears-more-than-once/ + 2025-01-04 + + + https://sfdx-hardis.cloudity.com/sf-deployment-assistant/sharing-operation-already-in-progress/ + 2025-01-04 + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 000000000..2bbb5c2c1 Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/special-thanks/index.html b/special-thanks/index.html new file mode 100644 index 000000000..24c61b188 --- /dev/null +++ b/special-thanks/index.html @@ -0,0 +1,7735 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Special Thanks about sfdx-hardis - Sfdx-Hardis Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Special Thanks

+ + + +

Trailblazer community

+ +

Contributors

+

+

Inspirations

+

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/stylesheets/extra.css b/stylesheets/extra.css new file mode 100644 index 000000000..b01f21eed --- /dev/null +++ b/stylesheets/extra.css @@ -0,0 +1,33 @@ +/* stylelint-disable SelectorFormat */ +.md-typeset__table { + min-width: 100%; +} + +.md-typeset table:not([class]) { + display: table; +} + +/* light mode table header bgcolor */ +.md-typeset__table th { + background-color: #f2edfe; +} + +/* dark mode table header bgcolor */ +[data-md-color-scheme="slate"] .md-typeset__table th { + background-color: hsla(var(--md-hue), 25%, 25%, 1) +} + +/* light mode alternating table bg colors */ +.md-typeset__table tr:nth-child(2n) { + background-color: #f8f8f8; +} + +/* dark mode alternating table bg colors */ +[data-md-color-scheme="slate"] .md-typeset__table tr:nth-child(2n) { + background-color: hsla(var(--md-hue), 25%, 25%, 1) +} + +:root>* { + --md-primary-fg-color: #1B1464; + --md-footer-bg-color: #1B1464; +} \ No newline at end of file