Is it possible to run or skip a job based on the output of a previous job?

I’m trying to see if I can make my dependency installation jobs as fast as possible. I’ve already made some significant improvements to my install_gems job that runs bundle install. CircleCI doesn’t have a way to check if a cache exists, so I made another very small cache for this purpose.

  • Just download a single file (Gemfile.lock) from GitHub
  • Restore the 'bundle-exists-{{ checksum "Gemfile.lock" }}' cache, which just contains a single empty file called bundle-exists
  • If bundle-exists is present, run circleci-agent step halt; exit 0
  • Otherwise, check out the source code, restore the cache, install gems, save the cache, touch bundle-exists, and save that “exists” cache as well

This is working really well, but now the main bottleneck is that I need to run this in a heavy Docker image (with build-essential, other Ruby libraries, etc.) I would like to run this initial cache check in a minimal Alpine Linux image, and then start a full bundle install job in the larger Docker image if the cache is missing.

So is there any way to conditionally run or skip a job based on the output of a previous job? Or is there a way to programmatically restart a job using a different Docker image?

Here’s my install_gems job so far:

jobs:
  install_gems:
    docker:
      - image: docspringcom/ci_base:c1e6ba3bb01a
        auth:
          username: $DOCKERHUB_USERNAME
          password: $DOCKERHUB_PASSWORD
    steps:
      - run:
          name: Download Gemfile.lock
          command: |
            FILE_PATH=Gemfile.lock
            URL="https://raw.githubusercontent.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BRANCH}/${FILE_PATH}"
            curl -H "Authorization: token ${GITHUB_PERSONAL_ACCESS_TOKEN}" "${URL}" > "${FILE_PATH}"
      - restore_cache:
          keys: ['bundle-exists-{{ checksum "Gemfile.lock" }}']
      - run: |
          if [[ -f bundle-exists ]]; then
            circleci-agent step halt
            exit 0
          fi
          rm -f *
      - checkout
      - restore_cache:
          keys:
            - bundle-{{ checksum "Gemfile.lock" }}
            - bundle
      - run:
          name: Install Gems
          command: |
            bundle check || bundle install --jobs 4 --retry 3
      - save_cache:
          key: bundle-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle
      - run: 'touch bundle-exists'
      - save_cache:
          key: bundle-exists-{{ checksum "Gemfile.lock" }}
          paths: ['bundle-exists']

Actually never mind, it looks like CircleCI caches Docker image layers, so the job actually only takes 5 seconds. I’m happy with that!