Deploying Apps to Heroku with GitHub Actions

Deploying Apps to Heroku with GitHub Actions

GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows us to automate our build, test, and deployment pipeline. This comes in handy to use with Cloud Application platforms like Heroku to automate our deployment process to make it start when pushing to a branch or creating a pull request.

Please note that Heroku does have an Integration with Github to work with Github Actions, but a couple months ago they had an information leak within their company. One of the measures they took to face this situation was to close this integration. They did open it afterwards but it was unstable and unreliable, so many people decided not to use their integration and just create it themselves. This is how to do it.

Creating the GitHub Action Workflow

First you need to create an empty .yml file which will contain the workflow. It should be located in the root of the project in .github/workflows.

Let's say we want to create an action that will deploy our app to heroku when our main branch is updated in GitHub. Our Github Action will look like this:

env:
HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
...
ENV_VARIABLES: ${{ secrets.ENV_VARIABLES }}
name: Update Main
on:
push:
branches:
- 'main'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install Heroku
run: |
npm install -g heroku
- uses: akhileshns/heroku-deploy@v3.12.12
with:
heroku_api_key: ${{env.HEROKU_API_KEY}}
heroku_app_name: ''
heroku_email: 'email@neocoast.com'
justlogin: true
- name: Update Main
run: |
chmod +x ./script/heroku/update.sh
./script/heroku/update.sh main

We are using Github Secrets to store our environment variables in GitHub

Let's explain what is happening here. When our branch main is updated on a push event, this workflow is triggered. Then we need to install the Cloud Application platform, in this case Heroku. You can choose which version you'd like to install.

Afterwards we use akhileshns/heroku-deploy action to handle the connection to Heroku. This is key so that we can log in and use the commands in heroku-cli. You will have to use your Heroku email, and the heroku_api_key. To generate it, go to your profile in Heroku, scroll down and click on “Generate API key”.

Once this is done, we run our bash script to handle the deploy. It receives the branch you want to deploy as a parameter, in case you don't want to deploy main but a different one (it happens).

set -e # Immediately exit if an error occurs
# Precondition: Being logged in to Heroku and the app exists
echo "Update Main started. You need to be logged in in Heroku."
branch=$2
: ${branch:= $(git branch | sed -n -e 's/^\* \(.*\)/\1/p')}
email=$(heroku whoami)
echo "Connect to App.."
heroku git:remote -a $1
echo "Connect to App.. done."
{
git rev-parse --is-shallow-repository && git fetch --prune --unshallow && echo "Shallowing.. done."
} || echo "Repository is Complete"
echo "Git Config.."
git config --global user.name $email
git config --global user.email $email
echo "Git Config.. done."
git fetch
git checkout $branch
echo "Deploying code..
git push -f heroku $branch:main
echo "Deploying code.. done."

First we fetch the branch and connect to our Heroku app.

Then we check if the repository is shallowed and unshallow it. Heroku requires that your repository is unshallowed and has the full commit history in order to deploy.

Finally we define which user is going to be responsible for doing the release. To deploy the code, ensure that you are on the desired branch and utilize the heroku-cli command. 🚀

Now when we make a push to main we will see the workflow run in the Actions tab of our project.

Just as we used the push event, you could also use the pull_request event with these events to update or create apps in Heroku as you please. The sky’s the limit.

on:
pull_request:
types: [opened, synchronize, reopened]

And voilà! Your project is fully synchronized with Heroku and ready to shine.