14

I have some questions and issues with my CI and CD solution.

Rails: 4.2

Capistrano: 3.4.0

The application is hosted on a private server.

Right now I have the workflow working with deploying development, staging and production via the terminal. I also hooked up Circle CI working good on these branches.

I cannot find how to setup Circle CI to use Capistrano to deploy. Everything is configured with the server user in the Capistrano config.

How do I give Circle CI SSH access to my deploy user? Because now I have to provide a password for the user.

p4sh4
  • 3,292
  • 1
  • 20
  • 33
davidwessman
  • 1,170
  • 8
  • 27

2 Answers2

9

Use SSH keys for authentication. You might as well use it for your own SSH sessions too, because it's more convenient and secure (a rare occasion!) than password authentication. Check out this tutorial on how to set it up.

Then, paste your private key to CircleCI in Project Settings -> SSH Permissions, as described here. You'd need to copy the private key from your local machine from the key pair whose public key you added to the deploy user on the server. CircleCI then will have SSH access to your server.

You can set the hostname to the domain that points to your server or your server's IP, or leave it blank so this key would be used in all hosts.

p4sh4
  • 3,292
  • 1
  • 20
  • 33
4

CircleCI Version 2 Build and Deploy with Workflows

Let's presume the following very basic PHP application. Apache config points to /web. Files and folders ending with * are ignored by Git.

__repo
  |__.circleci
  |  |__config.yml
  |__.git
  |__tests
  |  |__features
  |  |__behat.yml
  |__scripts
  |  |__deploy.sh
  |__web
  |  |__node_modules*
  |  |__index.php
  |  |__styles.scss
  |  |__gulpfile.js
  |  |__styles.css*
  |__.gitignore
  1. On the server create a new user and add it to the www-data group. Make it own the whole repo recursively. Let's presume this user is called repo-boss.

    $ chown -R repo-boss:www-data repo/

  2. On your local machine create a new SSH key pair. Add the private key to CircleCI's back-end and have a look at resulting fingerprint we'll need later. Add the public key to /home/repo-boss/.ssh/authorized_keys.

Now let's presume the deploy.sh script holds the following very basic commands.

#!/usr/bin/env bash

# Set script to exit on errors.
set -e

# Get script's absolute location.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# Change to repo root.
cd ${DIR};
cd ..

# Git pull.
git status
git pull

# Run Gulp.
cd web/
gulp sass

And now comes CircleCI's config.yml that makes that whole thing work (after you at least once pulled the necessary stuff onto the server, of course). deploy will only run when the tests finished successfully.

version: 2
jobs:
  build:
    docker:
      - image: circleci/php:7.1-apache-node-browsers

    working_directory: ~/repo-name

    steps:
      - checkout

      - run:
          name: Whatever you need to get your app up and running.
          command: |
            command1 # Have a look at https://github.com/leymannx/drupal-circleci-behat/blob/develop/.circleci/config.yml for a more detailed example.
            command3
            command4

      - run:
          name: Run Tests.
          command: |
            behat --no-snippets -f pretty -o std

  deploy:
    machine:
      enabled: true
    working_directory: ~/repo-name
    steps:
      - checkout
      - run:
          name: Fix ssh Could not resolve hostname
          command: |
            ssh-keyscan 123.45.67.89 >> ~/.ssh/known_hosts # Add live server IP to known hosts.
            ssh-keyscan 555.45.67.89 >> ~/.ssh/known_hosts # Dev server, too.

      - add_ssh_keys: # add private SSH key from CircleCI account based on fingerprint.
          fingerprints:
            - "14:09:a1:b2:b3:c4:d5:e6:f7:g8:h9:81:"

      - run:
          name: Deploy master.
          command: if [ "${CIRCLE_BRANCH}" == "master" ]; then ssh repo-boss@123.45.67.89 'cd /var/www/repo/scripts && . deploy.sh'; else echo "Skipped"; fi
      - run:
          name: Deploy develop.
          command: if [ "${CIRCLE_BRANCH}" == "develop" ]; then ssh repo-boss@555.45.67.89 'cd /var/www/repo/scripts && . deploy.sh'; else echo "Skipped"; fi

workflows:
  version: 2
  build-and-deploy:
    jobs:
      - build:
          filters:
            branches:
              only:
                - develop
                - master
      - deploy:
          requires:
            - build
          filters:
            branches:
              only:
                - develop
                - master

Of course, you don't need to use workflows. You also can achieve this in a basic waterfall. But I liked it much better to split the two parts build and deploy up into different concerted jobs.

leymannx
  • 5,138
  • 5
  • 45
  • 48
  • is this version 1 or 2 of circleci? – Moses Liao GZ May 07 '18 at 11:36
  • @MosesLiaoGZ – One year ago I guess this was v1. I now do it like this: https://github.com/leymannx/drupal-circleci-behat/blob/develop/.circleci/config.yml (Check the commented parts at the bottom, and you have to add a private key to Circle CI back-end and the matching public key to authorized_keys on server). – leymannx May 07 '18 at 14:13
  • but would be better if you guys follow fabric file way of doing things, cos after ssh into the server, there are a lot of commands to run – Moses Liao GZ May 07 '18 at 23:31
  • @MosesLiaoGZ – What commands you run on the server depends on you. Provide a deploy script which can be executed after you SSH'ed to the server. This script can hold any commands you need. – leymannx May 08 '18 at 06:08