Automating Deployments with GitHub, CircleCI, and Heroku

GitHub + Laravel setup

I created https://github.com/hirotoyoshidome/learn-laravel. Laravel installation steps are omitted, but you can scaffold with Docker if you do not want to pollute your local environment: https://github.com/hirotoyoshidome/docker-composer-laravel-mysql.

Create the project:

php artisan create-project laravel/laravel {appname} --prefer-dist

For clarity I made / render resources/views/hello.blade.php with “HelloWorld!!”.

Heroku prep

Create an account, install the CLI, and log in (heroku login). Create the app:

heroku create {appname} --buildpack heroku/php

Add a Procfile:

web: vendor/bin/heroku-php-apache2 public/

Force HTTPS in production (AppServiceProvider::boot). Deploy once manually:

git add .
git commit -m "add Heroku settings."
git remote add heroku https://git.heroku.com/{appname}.git
git push heroku master
heroku run php artisan key:generate

Visit https://{appname}.herokuapp.com/ to confirm it works.

CircleCI

Sign in with GitHub at https://circleci.com/, add the repository, and commit /.circleci/config.yml. My config:

version: 2
jobs:
  build:
    docker:
      - image: circleci/php:7.3-node-browsers
    steps:
      - checkout
      - run: sudo apt update
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "composer.json" }}
            - v1-dependencies-
      - run: composer install -n --prefer-dist
      - save_cache:
          key: v1-dependencies-{{ checksum "composer.json" }}
          paths:
            - ./vendor
      - restore_cache:
          keys:
            - node-v1-{{ checksum "package.json" }}
            - node-v1-
      - run: yarn install
      - save_cache:
          key: node-v1-{{ checksum "package.json" }}
          paths:
            - node_modules
      - run: cp .env.example .env
  deploy-prod:
    machine:
      image: circleci/classic:edge
    steps:
      - checkout
      - run: heroku maintenance:on --app ${HEROKU_APP_NAME_PROD}
      - run: |
          git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME_PROD.git master
      - run: heroku maintenance:off --app ${HEROKU_APP_NAME_PROD}
workflows:
  version: 2
  build_and_deploy:
    jobs:
      - build
      - deploy-prod:
          requires:
            - build
          filters:
            branches:
              only: master

If the build passes, the deploy job runs. Set the Heroku API key and app name as CircleCI environment variables. I tweaked the hello view, committed to master, and confirmed that the CircleCI jobs succeeded and the change appeared on the site.

Wrap-up

This was my first time using CircleCI, and it was surprisingly simple. Paid tiers may be required for serious production use, but for personal projects it is great. You can also build CI/CD on AWS (CodePipeline + CodeBuild) or Jenkins if that suits your stack.