Skip to content

DefactoSoftware/heroku-scripts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

heroku-scripts

A small bash CLI that wraps the Heroku CLI to run commands against every app in a pipeline stage.

Replaces the older Elixir version of this tool.

Requirements

  • macOS or Linux
  • bash (any version that ships with the OS is fine)
  • The heroku CLI, installed and authenticated (heroku login)

Install

curl -fsSL https://raw.githubusercontent.com/DefactoSoftware/heroku-scripts/main/install.sh | sh

Or manually:

curl -fsSL https://raw.githubusercontent.com/DefactoSoftware/heroku-scripts/main/bin/heroku-scripts -o ~/.local/bin/heroku-scripts
chmod +x ~/.local/bin/heroku-scripts

Authentication

The heroku CLI must be authenticated. heroku-scripts picks credentials in this order:

  1. HEROKU_API_KEY — if already set, it is used as-is, so HEROKU_API_KEY=… heroku-scripts … always works.
  2. 1Password — if HEROKU_SCRIPTS_OP_REF holds a 1Password secret reference and HEROKU_API_KEY is not set, the key is read once via the 1Password CLI (op) and reused for every call.
  3. Otherwise the heroku CLI's own stored login (heroku login) is used.

Why the 1Password option exists

If your heroku credentials are brokered by 1Password (shell plugin / desktop app), every heroku call triggers an interactive approval and account selector. pipeline-cmd runs heroku in parallel, backgrounded subshells with no controlling terminal, so those prompts can't be answered and the run stalls. Resolving the key once, up front sidesteps this: 1Password approves a single time and the exported key flows to every child process.

Store your Heroku API key in 1Password, then point the script at it (add this to your shell profile):

export HEROKU_SCRIPTS_OP_REF="op://Private/Heroku/credential"

Get the reference from the 1Password app (right-click a field → Copy Secret Reference) or op item get "Heroku" --format json.

Prefer not to configure the script? Use op run instead — no env var needed:

HEROKU_API_KEY="op://Private/Heroku/credential" op run -- heroku-scripts apps my-pipe staging

Usage

heroku-scripts apps <pipeline> <stage>
heroku-scripts pipeline-cmd <pipeline> <stage> "<heroku command>" [--concurrency=N] [--no-stream] [-a] [--table|--csv]
heroku-scripts pipeline-task <pipeline> <stage> <MixTask> [--concurrency=N]
heroku-scripts promote <app> <to-team> <pipeline> [--dry-run] [--yes]

Run heroku-scripts help for the full command list.

Examples

List every app in the staging stage of the my-pipe pipeline:

heroku-scripts apps my-pipe staging

Set a config var on every staging app:

heroku-scripts pipeline-cmd my-pipe staging "config:set EMAIL_SENDER=noreply@example.com"

pipeline-cmd prints one record per app. On a terminal it renders an aligned table; when the output is piped or redirected it switches to CSV (appname;output) so it stays easy to parse and grep. Force either with --table or --csv.

# on a terminal
appname        | output
---------------+-----------------------------------------
my-app         | EMAIL_SENDER: noreply@example.com
my-app-worker  | EMAIL_SENDER: noreply@example.com

# piped
appname;output
my-app;EMAIL_SENDER: noreply@example.com
my-app-worker;EMAIL_SENDER: noreply@example.com

Records stream out as each app finishes (in completion order), so output appears progressively instead of all at once at the end — table mode included, since the column width comes from the app list. Pass --no-stream to withhold output until every app finishes and print it sorted by app name — useful for reproducible, diff-friendly output.

Apps whose output is empty (e.g. config:get for a var that isn't set) are skipped by default, and a count of skipped apps is printed to stderr. Pass -a/--all to include them:

heroku-scripts pipeline-cmd my-pipe production "config:get ADFS_METADATA_URL"
# ...only apps that have the var...
# 18 app(s) with empty output skipped (use -a/--all to include them)

The output field is the app's raw combined heroku output, so it may span multiple lines and contain semicolons. Treat the stream as something to read or grep, not as strict CSV.

Run a mix task on every production app, four at a time:

heroku-scripts pipeline-task my-pipe production GiveRaiseToPeople --concurrency=4

Move an app and its -staging sibling to another team and pipeline:

heroku-scripts promote my-app my-team my-pipe

promote runs destructive, largely irreversible operations, so it prints what it will do and asks for confirmation first. Pass --dry-run to preview the exact heroku commands, or --yes to skip the prompt.

Development

Static analysis runs through ShellCheck and the test suite through bats; both run in CI on every push:

shellcheck bin/heroku-scripts install.sh
bats test

The tests stub the heroku CLI on PATH, so they never touch a real account.

About

A small bash CLI that wraps the Heroku CLI to run commands against every app in a pipeline stage.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages