How to keep your npm dependencies up-to-date without wasting your time

Keeping dependencies up-to-date became a hot topic lately. Having an old dependency in your dependency tree could jeopardize your entire codebase. When a dependency is old there is a high risk that it may contain security vulnerability. Npm now has it’s own security advisories website and npm cli is automatically checking your dependency trees for possible security vulnerabilities while installing them. Npm did a great job by embedding security vulnerability scan into it’s core and with GitHub’s dependabot ability to keep your dependencies up-to-date we’re looking into brighter and more secure future. Having worked in large corporation in past for almost two years, I would very much appreciate having these tools then. In large corporations the most important things are licenses and secure dependencies (in that order) and in order to be compliant with internal corporation policies we had to build our own tools for JavaScript ecosystem. Fortunately that’s not the case anymore.

Short history of dependabot

dependabot is a solution of automated dependency updates. Dependabot creates pull requests to keep your dependencies secure and up-to-date. First version of dependabot was developed by a company that was acquired by Github in May 2019. This first versions was never fully integrated into GitHub. Since then GitHub created a second version of fully GitHub integrated dependabot; I can say it’s one of the best automated dependency update tool I’ve seen so far.

But there are some challenges as well. First version of dependabot did come with auto-merge functionality. This meant that dependabot issued a PR with an update, your CI would run the checks and if checks passed, the dependabot would merge it’s own PR. This was a great productivity booster for public repositories maintaners (like me) as we no longer had to do it manually. Seconds versions of dependabot no longer have auto-merge functionality and it’s up to repositories maintainers to come up with the mechanism of merging dependabot’s PRs. You can do it manually, but I really wouldn’t recommend this as it’s a real time waster and you can surely invest your precious time better.

Now I’m gonna describe how to setup your own mechanism of auto-merge functionality on couple of my favorite CIs: CircleCI and GitHub Actions. The last thing I’m gonna show you is how to create auto-merge functionality on CI consisting of heterogeneous CI checks like mixed CircleCI, GitHub Actions, Fossa, CodeClimate etc… In further texts I’m assuming that you’re hosting your code on GitHub.

CircleCI auto-merge functionality

CircleCI is one of the best Continuous Integration tools I’ve seen so far. The tremendous thing about it is that it’s free for OpenSource and can be easily integrated with GitHub. It supports really complex workflows and have some features that GitHub Actions are missing.

No alt text provided for this image

Dependabot’s auto-merge functionality has been already implemented by other smart people in form of shareable configuration called CircleCI orbs. This means we don’t actually need to implement it we just need to use it.

Here is an example how it could be done:

version: 2.1
orbs:
  github: topmonks/github@1.0.2
jobs:
  build:
    # your build steps with tests
  merge_pr:
    docker:
      - image: cimg/base:2020.01
    steps:
      - checkout
      - github/install
      - github/merge_pr:
          rebase: true
workflows:
  ci:
    jobs:
     - build
     - merge_pr:
         context: github-cli
         requires:
           - build
         filters:
           branches:

             only: /dependabot/.*/

This workflow configuration is using topmonks/github CircleCI orb. The orb is using GitHub CLI to merge the dependabot’s PRs. As you can see it’s quite simple to integrate the merge_pr job into your workflow. This particular workflow requires build job to successfully complete before the merge_pr job is triggered. Author of the orb wrote a very well written article about the orb usage and explains in details how it works (Czech language only).

GitHub Actions auto-merge functionality

GitHub Actions is a CI/CD built directly into GitHub. After it’s been introduced, it’s my primary choice of writing a workflows. I don’t need to leave GitHub to write, run and check my workflows and that’s what I like about it – everything in one place. And again, it’s completely free for OpenSource.

No alt text provided for this image

GitHub Actions has it’s own system of creating shareable actions based on actions/toolkit. It even has it’s own GitHub Actions Markeplace. For implementing dependabot’s auto-merge functionality I recommend to use ridedott/merge-me-action GitHub Action. Here is example of a simple workflow.

name: Node.js CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  merge-me:
    name: Merge me!

    runs-on: ubuntu-latest

    needs: [ build ]

    strategy:
      matrix:
        node-version: [ 14.x ]

    steps:
      - name: Merge me!
        uses: ridedott/merge-me-action@master
        with:
          GITHUB_LOGIN: dependabot[bot]
          GITHUB_TOKEN: ${{ secrets.MERGE_ME_GITHUB_TOKEN }}
          MERGE_METHOD: SQUASH
          PRESET: DEPENDABOT_MINOR

  build:

    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [10.x, 12.x, 14.x]

    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - run: npm ci
    - run: npm run build --if-present
    - run: npm run lint
    - run: npm test
      env:
        CI: true

The merge-me job requires build jot to succeed before the PR is merge. There is one bump here: In order for GitHub Actions to successfully merge the PR and trigger workflows on master, it needs to use valid GITHUB_TOKEN. It is recommended not to use default repository GITHUB_TOKEN, as there is a measure in GitHub Actions that prevents us from accidentally creating recursive workflow runs.

Heterogeneous CI checks

Now we’re getting into fun part. Having a heterogeneous CI/CI is pretty common. We can easily get into this situation just by utilizing a code quality tool like CodeClimate.

No alt text provided for this image

You can see here, that all checks in workflow comes from CircleCI but one single check comes from CodeClimate. In this situation we cannot easily utilize topmonks/github CircleCI orb as CircleCI doesn’t know anything about CodeClimate check; it doesn’t know that it’s running nor it’s aware when it’s finished. The same applies for case when all the checks are GitHub Actions checks (or any other checks from any other CI/CD system).

After some research and prototyping I came into conclusion, that in this particular case I don’t really need to synchronize the checks but I’m only concerned about the final status of the PR. The status of PR is marked as success when all the checks have successfully passed. In order to implement something like that we can use simple GitHub Action workflow that will run as one of the CI/CD checks and will check for PR status periodically every n seconds until PR is marked as success. Only after that the PR is merged.

name: Merge me!

on:
  check_suite:
    types:
      - completed
  pull_request:
    types:
      - edited
      - labeled
      - opened
      - ready_for_review
      - reopened
      - synchronize
      - unlabeled
      - unlocked
jobs:
  merge-me:
    name: Merge me!
    if: github.actor == 'dependabot[bot]'
    runs-on: ubuntu-latest
    steps:
      - name: 'Wait for status checks'
        id: waitforstatuschecks
        uses: WyriHaximus/github-action-wait-for-status@v1
        with:
          ignoreActions: Merge me!
          checkInterval: 13
        env:
          GITHUB_TOKEN: ${{ secrets.MERGE_ME_GITHUB_TOKEN }}
      - name: Merge me!
        if: steps.waitforstatuschecks.outputs.status == 'success'
        uses: ridedott/merge-me-action@master
        with:
          GITHUB_LOGIN: dependabot[bot]
          GITHUB_TOKEN: ${{ secrets.MERGE_ME_GITHUB_TOKEN }}
          MERGE_METHOD: SQUASH
          PRESET: DEPENDABOT_MINOR

This GitHub Actions checks will run alongside with all the CircleCI and CodeClimate checks. Shareable custom GitHub Actions called WyriHaximus/github-action-wait-for-status@v1 is making all the magic here happen. The interesting thing about this GitHub Action is that it’s implemented in PHP.

Don’t forget to enable required status checks on your repository before utilizing auto-merge mechanism. Without it, dependabot’s PR may be merged before all your checks have successfully ran. Only with required status checks enabled PR actually knows when it’s status become success – when all checks that has been flagged as required passes.

Hopefully this article will help you save some of your valuable time by showing you the beauty of the automation. If you have to do something repeatedly it probably can be automated. Automation requires a time investment to implement but it will pay off with time dividends in future.

PS: during this research I didn’t find a way how to actually synchronize checks comming from different sources – GitHub Actions, CircleCI, CodeClimate, Fossa, etc…. Currently I do think there is no way to synchronize them (e.g. running GitHub Actions checks after CircleCI checks), but I welcome you to prove me wrong and describe a possible orchestration mechanism in comments.

Published By

Author: Shantun Parmar

Leave a Reply

Your email address will not be published.