Deploy to Heroku with GitHub Actions


This article goes over how to deploy to Heroku using the GitHub Actions workflow.

Prerequisites

Heroku

Create a Heroku app and save the app’s name and email associated with your account. Then go to Account settings and copy your API Key.

GitHub

Go to your GitHub repository’s Settings > Secrets and set the secrets:

  • HEROKU_API_KEY
  • HEROKU_APP_NAME
  • HEROKU_EMAIL

GitHub Action

Workflow to deploy using Deploy to Heroku action:

# .github/workflows/heroku-deploy.yml
jobs:
  heroku-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v3
      - name: Deploy to Heroku
        uses: akhileshns/heroku-deploy@v3.12.12
        with:
          heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
          heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
          heroku_email: ${{ secrets.HEROKU_EMAIL }}

The action pushes to the main branch.

Check out the additional options.

Custom Workflow

Workflow to deploy using a custom job:

# .github/workflows/custom-deploy.yml
jobs:
  custom-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - name: Heroku login credentials
        run: |
          cat > ~/.netrc <<EOF
            machine api.heroku.com
              login $HEROKU_EMAIL
              password $HEROKU_API_KEY
            machine git.heroku.com
              login $HEROKU_EMAIL
              password $HEROKU_API_KEY
          EOF
        env:
          HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
          HEROKU_EMAIL: ${{ secrets.HEROKU_EMAIL }}
      - name: Add Heroku remote
        run: heroku git:remote --app $HEROKU_APP_NAME
        env:
          HEROKU_APP_NAME: ${{ secrets.HEROKU_APP_NAME }}
      - name: Push to Heroku
        run: git push heroku master

The differences between the 2 workflows are explained below.

Checkout

The Checkout action must fetch the entire Git history or else the build will fail with the error:

Run git push heroku master
  git push heroku master
  shell: /usr/bin/bash -e {0}
remote:
remote: !	Push rejected, source repository is a shallow clone. Unshallow it with `git fetch --all --unshallow` and try pushing again.
remote:
To https://git.heroku.com/***.git
 ! [remote rejected] master -> master (shallow update not allowed)
error: failed to push some refs to 'https://git.heroku.com/***.git'
Error: Process completed with exit code 1.

Heroku Login

The ~/.netrc contains the Heroku login credentials:

- name: Heroku login credentials
  run: |
    cat > ~/.netrc <<EOF
      machine api.heroku.com
        login $HEROKU_EMAIL
        password $HEROKU_API_KEY
      machine git.heroku.com
        login $HEROKU_EMAIL
        password $HEROKU_API_KEY
    EOF
  env:
    HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
    HEROKU_EMAIL: ${{ secrets.HEROKU_EMAIL }}

Deploy with Git

Then the Git remote is set and pushed:

- name: Add Heroku remote
  run: heroku git:remote --app $HEROKU_APP_NAME
  env:
    HEROKU_APP_NAME: ${{ secrets.HEROKU_APP_NAME }}
- name: Push to Heroku
  run: git push heroku master

We are pushing to the master branch here, but we can push to main as well.

Example

The repository contains the code examples.

See how a successful deploy will look like.
Created and wrote to ~/.netrc
Successfully logged into heroku
 ›   Warning: Our terms of service have changed:
Added git remote heroku
 ›   https://dashboard.heroku.com/terms-of-service
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Node.js app detected
remote:
remote: -----> Creating runtime environment
remote:
remote:        NPM_CONFIG_LOGLEVEL=error
remote:        NODE_VERBOSE=false
remote:        NODE_ENV=production
remote:        NODE_MODULES_CACHE=true
remote:
remote: -----> Installing binaries
remote:        engines.node (package.json):  unspecified
remote:        engines.npm (package.json):   unspecified (use default)
remote:
remote:        Resolving node version 14.x...
remote:        Downloading and installing node 14.16.0...
remote:        Using default npm version: 6.14.11
remote:
remote: -----> Restoring cache
remote:        - node_modules
remote:
remote: -----> Installing dependencies
remote:        Installing node modules (package.json)
remote:        audited 50 packages in 0.733s
remote:        found 0 vulnerabilities
remote:
remote:
remote: -----> Build
remote:
remote: -----> Caching build
remote:        - node_modules
remote:
remote: -----> Pruning devDependencies
remote:        audited 50 packages in 0.735s
remote:        found 0 vulnerabilities
remote:
remote:
remote: -----> Build succeeded!
remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> web
remote:
remote: -----> Compressing...
remote:        Done: 32.6M
remote: -----> Launching...
remote:        Released v6
remote:        https://***.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/***.git
   88f00ab..1a1a302  HEAD -> main



Please support this site and join our Discord!