Command line tool supporting the Force.com development lifecycle
Reduced maintenance for
force-dev-tool
force-dev-toolhas been created in 2015 trying to provide a CLI for developers to do deployments leveraging Version Control Systems because i felt a need to improve the painful Software Development Lifecycle for Salesforce.Fortunately times have changed.
If you're looking for a modern Software Development Lifecycle for Salesforce please get familiar with Salesforce DX and use the official Salesforce CLI (a.k.a. sfdx-cli).
$ npm install --global force-dev-tool$ force-dev-tool --help
force-dev-tool.
Usage:
  force-dev-tool <command> [<args>...]
  force-dev-tool -h | --help
  force-dev-tool --version
Options:
  -h --help       Show this screen.
  --version       Show version.
Commands:
  help            Print help for a command or in general
  remote          Manage orgs (list, add, remove, set default, set password)
  login           Login using Metadata API and show login URL
  fetch           Fetch describe information from a remote
  info            Show describe information from a remote
  package         Generate a package.xml file from local describe information
  retrieve        Retrieve metadata specified in package.xml
  deploy          Deploy metadata specified in a package.xml
  test            Execute unit tests
  changeset       Create a changeset/deployment from a unified diff input or cli args
  query           Execute a SOQL query returing JSON
  bulk            (alpha) Import/export data in CSV format using the bulk API
  execute         (alpha) Execute anonymous Apex
See 'force-dev-tool help <command>' for more information on a specific command.Managing remote environments
$ force-dev-tool remote add mydev user pass --default
$ force-dev-tool remote add build user pass2
$ force-dev-tool remote add production user pass3 https://login.salesforce.comValidating credentials for a given remote (optional)
$ force-dev-tool login mydev
Logged in successfully to remote mydev.
Use the following URL to open Salesforce in your web browser:
https://mynamespace.my.salesforce.com/secur/frontdoor.jsp?sid=REDACTEDBuilding a manifest
Fetch various information from the remote first
$ force-dev-tool fetch --progress
Fetching from remote mydev
API Versions
Available Metadata Types
Folders
Metadata Components
RecordTypes of PersonAccount
Active Flow versions
Created config/mydev-fetch-result.json
Fetching remotes finished.Now generate a package.xml file based on the fetched information
$ force-dev-tool package -a
Created src/package.xmlIn order to exclude certain metadata components from being added to the package.xml file, add patterns (similar to .gitignore) to .forceignore. See here for some sane default rules.
Retrieving metadata
$ force-dev-tool retrieve
Retrieving from remote mydev to directory src
SucceededCreating deployments
1. By explicitly listing metadata files or metadata components
$ echo "" | force-dev-tool changeset create vat src/pages/AccountExtensionVAT.page CustomField/Account.VAT__c2. By providing a unified diff (e.g. git diff). Tweak the git diff command with --ignore-space-at-eol or --ignore-all-space to ignore space changes.
$ git diff --no-renames master feature/vat | force-dev-tool changeset create vatBoth approaches lead to the following result
Manifest:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
 <types>
     <members>Account.VAT__c</members>
     <name>CustomField</name>
 </types>
 <types>
     <members>AccountExtensionVAT</members>
     <name>ApexPage</name>
 </types>
 <version>38.0</version>
</Package>
exported metadata container to config/deployments/vatCreating destructive deployments (reverting changes)
1. By explicitly listing metadata files or metadata components
$ echo "" | force-dev-tool changeset create undo-vat --destructive src/pages/AccountExtensionVAT.page CustomField/Account.VAT__c2. By providing a unified diff (e.g. git diff)
$ git diff --no-renames feature/vat master | force-dev-tool changeset create undo-vatBoth approaches lead to the following result
Manifest:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
 <version>38.0</version>
</Package>
Destructive Manifest:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
 <types>
     <members>Account.VAT__c</members>
     <name>CustomField</name>
 </types>
 <types>
     <members>AccountExtensionVAT</members>
     <name>ApexPage</name>
 </types>
</Package>
exported metadata container to config/deployments/undo-vatDeploying metadata
$ force-dev-tool deploy --help
Usage:
  force-dev-tool deploy [options] [<remote>]
Deploy metadata specified in a package.xml.
Options:
  -c --checkOnly           Perform a test deployment (validation).
  -t --test                Run local tests.
  --runTests=<classNames>  Names of test classes (one argument, separated by whitespace).
  --runAllTests            Run all tests including tests of managed packages.
  --purgeOnDelete          Don't store deleted components in the recycle bin.
  --noSinglePackage        Allows to deploy multiple packages.
  -d=<directory>           Directory to be deployed [default: src].
  -f=<zipFile>             Zip file to be deployed.
Examples:
  Deploying the default directory to the default remote
    $ force-dev-tool deploy
    Running Deployment of directory src to remote mydev
    Visit https://mynamespace.my.salesforce.com/changemgmt/monitorDeploymentsDetails.apexp?asyncId=REDACTED for more information.
  Deploying to another remote
    $ force-dev-tool deploy myqa
  Deploying a specified directory
    $ force-dev-tool deploy -d config/deployments/vat
  Perform a test deployment (validation)
    $ force-dev-tool deploy --checkOnly
    $ force-dev-tool deploy -c
  Deploying with running local tests
    $ force-dev-tool deploy -t
    $ force-dev-tool deploy --test
  Deploying with running specified test classes
    $ force-dev-tool deploy --runTests 'Test_MockFoo Test_MockBar'
  Deploying with running test classes matching a pattern
    $ force-dev-tool package grep 'ApexClass/Test_Mock*' \
     | cut -d '/' -f 2 \
     | xargs -0 force-dev-tool deploy --runTests
  Deploying with running only test classes being contained in a deployment
    $ force-dev-tool package -f config/deployments/mock/package.xml grep 'ApexClass/Test_*' \
     | cut -d '/' -f 2 \
     | xargs -0 force-dev-tool deploy -d config/deployments/mock --runTestsRunning unit tests
Running all local tests
$ force-dev-tool test
Running Test execution to remote mydev
Failures:
Test_Foo#test_method_one took 32.0
  - System.AssertException: Assertion Failed: Expected: foo, Actual: bar
  - Class.Test_Foo.test_method_one: line 8, column 1
Test_Foo2#test_method_one took 11.0
  - System.AssertException: Assertion Failed
  - Class.Test_Foo2.test_method_one: line 7, column 1
Error: Visit https://mynamespace.my.salesforce.com/changemgmt/monitorDeploymentsDetails.apexp?asyncId=REDACTED for more information.
3 methods, 2 failures
$ force-dev-tool test build
Running Test execution to remote build
Failures:
Test_Foo#test_method_one took 32.0
  - System.AssertException: Assertion Failed: Expected: foo, Actual: bar
  - Class.Test_Foo.test_method_one: line 8, column 1
Test_Foo2#test_method_one took 11.0
  - System.AssertException: Assertion Failed
  - Class.Test_Foo2.test_method_one: line 7, column 1
Error: Visit https://mynamespace.my.salesforce.com/changemgmt/monitorDeploymentsDetails.apexp?asyncId=REDACTED for more information.
3 methods, 2 failuresRunning specified test classes
$ force-dev-tool test --classNames 'Test_MockFoo Test_MockBar'Running test classes matching a pattern (in src/package.xml)
$ force-dev-tool package grep 'ApexClass/Test_Mock*' \
 | cut -d '/' -f 2 \
 | xargs -0 force-dev-tool test --classNamesUsing force-dev-tool in a build script
The following environment variables can be used to define a default remote environment called env:
- SFDC_USERNAME
- SFDC_PASSWORD
- SFDC_SERVER_URL
$ force-dev-tool deploy -ct envNote: You can also define named remotes using Environment Variables (e.g. SFDC_ci_USERNAME, SFDC_ci_PASSWORD, SFDC_ci_SERVER_URL).
Executing a SOQL query
$ force-dev-tool query "SELECT Id, Name FROM Account LIMIT 1"
[
  {
    "attributes": {
      "type": "Account",
      "url": "/services/data/v38.0/sobjects/Account/001200000183ZCFAA2"
    },
    "Id": "001200000183ZCFAA2",
    "Name": "GenePoint"
  }
]
$ force-dev-tool query "SELECT COUNT(Id) c FROM Account"
[
  {
    "attributes": {
      "type": "AggregateResult"
    },
    "c": 15
  }
](alpha) Exporting/importing data using the bulk API
Exporting data
$ force-dev-tool bulk export "SELECT Id, Name FROM Account LIMIT 1"
"Id","Name"
"001200000183ZCFAA2","GenePoint"
$ force-dev-tool bulk export "SELECT Id, Name FROM Account" --out Accounts.csvUpdating data
$ force-dev-tool bulk update Account --in Accounts.csv --out Accounts-update-results.csvNote: Importing more than one batch is currently not yet supported.
(alpha) Executing anonymous Apex
$ echo "insert new Account(Name = 'Test Account');" | force-dev-tool executePlease see the wiki for Motivation and Troubleshooting and Resources.
Feel free to open issues with questions.
MIT © Matthias Rolke