When doing development on Heroku using review apps, pipelines and all the other goodness it’s sometimes required to test against a clone of a production database. Doing that is pretty easy on Heroku when you know how even without moving the data down to your own laptop and then backup to Heroku. This is done by creating a backup, generating a public, secret, URL for the backup image and then restoring from that URL.
Below are the steps in the Heroku CLI to clone a database from an app called “my-production-app” to an app called “my-development-app”. Step no. 3 is to create a new Heroku Postgres addon attached to “my-development-app” that fits the same amount of data as the one from “my-production-app”.
$ heroku pg:backups:capture --app my-production-app
Starting backup of postgresql-aerodynamic-55964… done
Use Ctrl-C at any time to stop monitoring progress; the backup will continue running.
Use heroku pg:backups:info to check progress.
Stop a running backup with heroku pg:backups:cancel.
Backing up DATABASE to b003… done
$ heroku pg:backups:url --app my-production-app b003
$ heroku addons:create heroku-postgresql:hobby-basic --app my-development-app
Creating heroku-postgresql:hobby-basic on ⬢ my-development-app… $9/month
Database has been created and is available
! This database is empty. If upgrading, you can transfer
! data from another database with pg:copy
Created postgresql-octagonal-31270 as HEROKU_POSTGRESQL_YELLOW_URL
Use heroku addons:docs heroku-postgresql to view documentation
$ heroku pg:backups:restore --app my-development-app https://xfrtu.s3.amazonaws.com/112d4cf2-xxxx-475b-xxxx-ac809400fa78… HEROKU_POSTGRESQL_YELLOW
Once restored you may promote the database you restored into using the “heroku pg:promote” command and / or delete the backup you created.
$ heroku pg:backup:delete --app my-production-app b003
▸ WARNING: Destructive Action
▸ This command will affect the app my-production-app
▸ To proceed, type my-production-app or re-run this command with --confirm
Now this is very good news for us that are doing scripting with Salesforce DX. Currently the Salesforce DX CLI (sfdx) will send its output to stdout (standard out) when the command succeeds and to stderr (standard error) if the command fails. Why would a command fail? Well if you try and describe an org with a wrong or non-existing alias that’s one reason.
Now this is really the expected behaviour for a CLI but when doing scripting using the –json flag to always have the response returned as JSON it just makes it more complicated. For one the response already have a “status”-flag to indicate whether the invocation was successful or not. Secondly having to deal with stdout and stderr is not difficult but leads to boilerplate scripting code as what you really want to do is capture the response and check that “status”-flag in the JSON. Also it makes it harder to adopt for people new to CLI scripting and the way it’s done across platforms differ.
Now to the good news.
As of v44, there is an environment variable to have all JSON output go to stdout. Set SFDX_JSON_TO_STDOUT=true to get this new behaviour. This will become the default behaviour in v45. Now it’s not listed on the environment variables list for Salesforce DX yet but I trust it will be soon.
macOS was just recently approved by Salesforce IT so I upgraded but only to find that my heroku CLI and SalesforceDX CLI tools had stopped working. I seem to remember that SalesforceDX is basically the same as the Heroku CLI so them failing together made sense. Running the tools only gave strange errors…
stat /Users/mheisterberg/.local/share/heroku/client/bin/heroku: not a directory
fork/exec /Users/mheisterberg/.local/share/heroku/client/bin/heroku: not a directory
stat /Users/mheisterberg/.local/share/sfdx/client/bin/sfdx: not a directory
panic: fork/exec /Users/mheisterberg/.local/share/sfdx/client/bin/sfdx: not a directory
goroutine 1 [running]:
main.getExitCode(0x3c03c0, 0xc420017350, 0xc420017350)
I started thinking it was an issue with node but it turned out to be caused by the command line tools for macOS having been uninstalled or needing to be updated. Below are the steps I used to install the command line tools, upgrade node (I’m using Homebrew) and fix the Heroku CLI and SalesforceDX CLI.
// update / install command line tools for macOS
$ xcode-select --install
// update homebrew
$ brew update
// verify my node version
$ node --version
// upgrade node
$ brew upgrade node
==> Upgrading 1 outdated package, with result:
// now to the real magic - fix heroku cli
$ rm -rf ~/.local/share/heroku/client
$ heroku update
heroku-cli: Updating to 6.14.43-73d5876... 12.7 MB/12.7 MB
heroku-cli: Updating CLI... already on latest version: 6.14.43-73d5876
heroku-cli: Updating plugins... done
$ heroku --version
heroku-cli/6.14.43-73d5876 (darwin-x64) node-v9.2.0
// rinse and repeat for SalesforceDX cli
$ rm -rf ~/.local/share/sfdx/client
$ sfdx update
sfdx-cli: Updating to 6.0.26-3d23012... 19.3 MB/19.3 MB
Installing dependencies for /Users/mheisterberg/Programming/repos/sfdx-l18n-plugin... done
sfdx-cli: Updating CLI... already on latest version: 6.0.26-3d23012
sfdx-cli: Updating plugins... done
$ sfdx --version
sfdx-cli/6.0.26-3d23012 (darwin-x64) node-v8.6.0
Today when at a customer we were trying to figure out the release versions the various sandboxes and development environments and compare this info with the version of the production instance. Of course all this is available from status.salesforce.com but clicking around got a bit tedious so I whipped up a quick set of bash aliases for the Terminal. Since the output is also available as JSON it was pretty easy. First I grabbed the jq JSON parser for bash and then I wrote 4 aliases for bash:
- sf_instance – returns the instance ID (e.g. “na44”) from the hostname. This is useful if you are using a custom domain to access the instance e.g. lekkim-trailhead-dev-ed.my.salesforce.com
- sf_release – shows only the release the instance is on e.g. “Spring ’17 Patch 5.5”
- sf_status – shows release version, whether active or not and type of instance (production, sandbox etc)
- sf_status_raw – returns the raw JSON
Below are examples of usage and the ailases are at github.com/lekkimworld/sf_aliases.
Salesforce CLI actions:
Shows status for instance ID
Syntax : sf_status
Example: sf_status na44
Shows release version of supplied instance ID
Example: sf_release na44
Get instance ID from hostname
Example: sf_instance org62.lightning.force.com
Shows raw JSON
$ sf_instance na44.salesforce.com
$ sf_instance lekkim-trailhead-dev-ed.my.salesforce.com
$ sf_release eu11
Winter '17 Patch 18.10
$ sf_release na44
Spring '17 Patch 5.5
$ sf_status eu11
Release Version : Winter '17 Patch 18.10
Active : true
Status : OK
Environment : production
$ sf_status cs85
Release Version : Spring '17 Patch 6
Active : true
Status : OK
Environment : sandbox
Stumbled on this very nice easy way to export to a delimited file from the DB2 Command Line Prompt (CLI) today.
db2 “EXPORT TO <filename> OF DEL MODIFIED BY NOCHARDEL <select statement>”
db2 “EXPORT TO result.csv OF DEL MODIFIED BY NOCHARDEL select * from empinst.employee”