Automate Github Dependabot with Actions

Every so often I will get a notification that a project of mine has a dependabot alert. I usually fetch my code, run npm audit fix or pip install –upgrade, and commit my code. It can be automated.

In this post I will show you how to automate the following:

  • Allow dependabot to essentially run npm audit fix or pip install –upgrade etc and create a PR with the fix.
  • Create a Github Action to acutally merge the PR into your main branch.


Allow Dependabot to create a PR with the updated module

This one is super easy.

Go to your repo’s settings and enable “Dependabot Security Updates”. It is a good idea to also enable “Dependabot alerts” so that you can get email notifications whenever a vulnerability in one of the npm or pip etc packages you use is found.

Dependabot Security Updates


Dependabot should create a PR almost immediately if you have open dependabot alerts and you will see a PR much like this one:

PR created automatically by dependabot


Create a Github Action to Merge the PR

This Github Action will automatically trigger whenever dependabot opens a PR, but it also allows you to manually kick off this Action just in case you have to.

But first, enable this setting to allow Actions to “create and approve pull requests”.

Github Actions create and approve pull requests


Next, add this Action to your “.github/workflows/dependabot-auto-merge.yml” file. You can name the file anything you’d like.

name: Dependabot Auto-Merge
on:
  pull_request:
    types: [opened, synchronize, reopened]
  workflow_dispatch: 

permissions:
  contents: write
  pull-requests: write

# Prevent concurrent merges from conflicting with each other
concurrency:
  group: dependabot-merge-${{ github.ref }}
  cancel-in-progress: false

jobs:
  dependabot:
    runs-on: ubuntu-latest
    if: github.actor == 'dependabot[bot]' || github.event_name == 'workflow_dispatch'
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Approve and Merge
        run: |
          if [ "${{ github.event_name }}" == "pull_request" ]; then
            PR_URL="${{ github.event.pull_request.html_url }}"
            echo "Processing trigger PR: $PR_URL"
            gh pr review --approve "$PR_URL" || echo "Already approved"
            # Use --admin to bypass requirements and merge immediately
            gh pr merge --merge --admin "$PR_URL"
          else
            echo "Processing all Dependabot PRs..."
            # Note: filter for 'app/dependabot' or 'dependabot[bot]' depending on your environment
            for pr in $(gh pr list --author "app/dependabot" --json url --jq '.[].url'); do
              echo "Merging $pr..."
              gh pr review --approve "$pr" || echo "Already approved or failed to approve $pr"
              gh pr merge --merge --admin "$pr" || echo "Failed to merge $pr"
            done
          fi
        env:
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

Here is output from the Action showing that 1 PR was merged:

Github Action output showing that 1 PR was merged


Keep in mind, this code does NOT run any tests, the “–merge –admin” basically forces the merge. It is up to you to add some proper tests before just blindly merging a PR.


Create an Docker Auto Build Action

The below will run on a schedule, call the GtiHub API to check for commits (super fast) and then continue with the build if it found any commits. You can also still kick it off manually.

name: build_docker_image

on:
  schedule:
    # Runs at 11:51 UTC every day
    - cron: '51 11 * * *'
  workflow_dispatch: 

jobs:
  login_build_push:
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read
    steps:
      - name: Check for recent commits via API
        id: check_changes
        run: |
          # Calculate timestamp for 24 hours ago (ISO 8601)
          SINCE=$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ)
          
          # Query GitHub API for commits since that timestamp
          RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
            "https://api.github.com/repos/${{ github.repository }}/commits?since=$SINCE")
          
          # Count elements in the returned JSON array
          COMMIT_COUNT=$(echo "$RESPONSE" | jq '. | length')

          if [ "$COMMIT_COUNT" -gt 0 ]; then
            echo "Found $COMMIT_COUNT commits in the last 24h. Proceeding."
            echo "should_build=true" >> $GITHUB_OUTPUT
          elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
            echo "Manual trigger detected. Proceeding."
            echo "should_build=true" >> $GITHUB_OUTPUT
          else
            echo "No changes in the last 24h. Skipping."
            echo "should_build=false" >> $GITHUB_OUTPUT
          fi

      - name: Checkout Code
        if: steps.check_changes.outputs.should_build == 'true'
        uses: actions/checkout@v4
        # We only need the current state for the Docker build
        with:
          fetch-depth: 1

      - name: Login to GitHub Container Registry
        if: steps.check_changes.outputs.should_build == 'true'
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and Push Image
        if: steps.check_changes.outputs.should_build == 'true'
        run: |
          IMAGE_NAME="ghcr.io/${{ github.actor }}/${{ github.event.repository.name }}"
          
          echo "Building $IMAGE_NAME:latest..."
          docker build . --tag "$IMAGE_NAME:latest"
          docker push "$IMAGE_NAME:latest"

necrolingus

Tech enthusiast and home labber