Skip to content

CI/CD Integration

Integrate depkeeper into your CI/CD pipeline for automated dependency monitoring and updates.


Overview

depkeeper fits into CI/CD workflows for:

  • Monitoring: Alert when dependencies are outdated
  • Reporting: Generate dependency reports
  • Automation: Automatically update dependencies
  • Security: Flag vulnerable packages (coming soon)

Important

The examples use src/requirements.txt -- replace with your actual requirements file path.


GitHub Actions

Check for Outdated Dependencies

Create .github/workflows/dependency-check.yml:

YAML
name: Dependency Check

on:
  schedule:
    # Run every Monday at 9 AM UTC
    - cron: '0 9 * * 1'
  workflow_dispatch:  # Manual trigger

jobs:
  check:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install depkeeper
        run: pip install depkeeper

      - name: Check dependencies and report
        run: |
          echo "Checking for outdated dependencies:"
          depkeeper check src/requirements.txt --outdated-only --format table

          # Fail if outdated dependencies are found
          if depkeeper check src/requirements.txt --outdated-only --format json 2>/dev/null | grep -q '"status": "outdated"'; then
            echo ""
            echo "❌ Build failed: Outdated dependencies detected. Please update them."
            exit 1
          fi

Automated Dependency Updates

Create .github/workflows/dependency-update.yml:

YAML
name: Dependency Update

on:
  schedule:
    - cron: '0 9 * * 1'  # Weekly on Monday
  workflow_dispatch:

jobs:
  update:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: |
          sudo apt-get update && sudo apt-get install -y jq
          pip install depkeeper
          pip install -r src/requirements.txt

      - name: Check for updates
        id: check
        run: |
          depkeeper check src/requirements.txt --outdated-only --format json > outdated.json
          echo "count=$(cat outdated.json | jq length)" >> $GITHUB_OUTPUT

      - name: Update dependencies
        if: steps.check.outputs.count > 0
        run: depkeeper update src/requirements.txt -y

      - name: Run tests
        if: steps.check.outputs.count > 0
        run: |
          cd src
          pytest

      - name: Generate update report
        if: steps.check.outputs.count > 0
        run: |
          echo "UPDATES_LIST<<EOF" >> $GITHUB_ENV
          cat outdated.json | jq -r '.[] | "- **\(.name)**: \(.versions.current) → \(.versions.recommended)"'
          echo "EOF" >> $GITHUB_ENV

      - name: Commit and push changes
        if: steps.check.outputs.count > 0
        run: |
          git config --global user.name "github-actions[bot]"
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
          git checkout -b deps/automated-updates
          git add src/requirements.txt
          git commit -m "chore(deps): update dependencies"
          git push -f origin deps/automated-updates

      - name: Create Pull Request
        if: steps.check.outputs.count > 0
        uses: actions/github-script@v7
        with:
          script: |
            const { data: pulls } = await github.rest.pulls.list({
              owner: context.repo.owner,
              repo: context.repo.repo,
              head: `${context.repo.owner}:deps/automated-updates`,
              state: 'open'
            });

            const prBody = `Automated dependency updates by depkeeper.

            ## Updated packages
            ${process.env.UPDATES_LIST}`;

            if (pulls.length === 0) {
              await github.rest.pulls.create({
                owner: context.repo.owner,
                repo: context.repo.repo,
                title: '⬆️ Update dependencies',
                head: 'deps/automated-updates',
                base: 'master',
                body: prBody
              });
            } else {
              await github.rest.pulls.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                pull_number: pulls[0].number,
                body: prBody
              });
            }

GitLab CI

.gitlab-ci.yml

YAML
stages:
  - check
  - update

variables:
  PYTHON_VERSION: "3.11"

dependency-check:
  stage: check
  image: python:${PYTHON_VERSION}
  script:
    - pip install depkeeper
    - depkeeper check src/requirements.txt --outdated-only --format json > deps-report.json || true
    - depkeeper check src/requirements.txt --outdated-only --format table || true
  artifacts:
    paths:
      - deps-report.json
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_PIPELINE_SOURCE == "web"

dependency-update:
  stage: update
  dependencies: [dependency-check]
  image: python:${PYTHON_VERSION}
  script:
    - pip install depkeeper pytest
    - |
      COUNT=$(python -c "import json,sys; data=open('deps-report.json').read().strip(); print(len(json.loads(data)) if data else 0)" 2>/dev/null || echo "0")
      if [ "$COUNT" -eq 0 ]; then
        echo "No outdated dependencies. Skipping update."
        exit 0
      fi
    - depkeeper update src/requirements.txt --backup -y
    - pip install -r src/requirements.txt
    - cd src && pytest
  artifacts:
    paths:
      - src/requirements.txt
      - src/requirements.txt.backup.*
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
      when: manual
    - if: $CI_PIPELINE_SOURCE == "web"
      when: manual

Azure Pipelines

azure-pipelines.yml

YAML
trigger: none

schedules:
  - cron: '0 9 * * 1'
    displayName: Weekly dependency check
    branches:
      include:
        - main

pool:
  vmImage: 'ubuntu-latest'

steps:
  - task: UsePythonVersion@0
    inputs:
      versionSpec: '3.11'

  - script: pip install depkeeper
    displayName: Install depkeeper

  - script: |
      depkeeper check src/requirements.txt --outdated-only --format json \
        > $(Build.ArtifactStagingDirectory)/deps.json || true
    displayName: Check dependencies (JSON report)

  - script: |
      depkeeper check src/requirements.txt --outdated-only --format table || true
    displayName: Show outdated packages

  - task: PublishBuildArtifacts@1
    condition: always()
    inputs:
      pathToPublish: '$(Build.ArtifactStagingDirectory)'
      artifactName: dependency-report

Jenkins

Jenkinsfile

Groovy
pipeline {
    agent {
        docker {
            image 'python:3.11'
        }
    }

    triggers {
        cron('H 9 * * 1')  // Weekly on Monday
    }

    stages {
        stage('Setup') {
            steps {
                sh 'apt-get update && apt-get install -y jq'
                sh 'pip install depkeeper'
            }
        }

        stage('Check Dependencies') {
            steps {
                sh '''
                    depkeeper check src/requirements.txt --outdated-only --format json \
                        > deps-report.json || echo "[]" > deps-report.json
                '''
                sh 'depkeeper check src/requirements.txt --outdated-only --format table || true'
            }
        }

        stage('Archive Report') {
            steps {
                archiveArtifacts allowEmptyArchive: true, artifacts: 'deps-report.json'
            }
        }
    }

    post {
        always {
            script {
                if (fileExists('deps-report.json')) {
                    def outdated = sh(
                        script: 'jq length deps-report.json || echo 0',
                        returnStdout: true
                    ).trim()

                    if (outdated.toInteger() > 0) {
                        currentBuild.description = "⚠️ ${outdated} outdated dependencies"
                    }
                } else {
                    echo "deps-report.json not found — skipping outdated count."
                }
            }
        }
    }
}

CircleCI

.circleci/config.yml

YAML
version: 2.1

jobs:
  dependency-check:
    docker:
      - image: cimg/python:3.11
    steps:
      - checkout
      - run:
          name: Install depkeeper
          command: pip install depkeeper
      - run:
          name: Export outdated deps as JSON
          command: depkeeper check src/requirements.txt --outdated-only --format json > deps-report.json || true
      - run:
          name: Show outdated deps as table
          command: depkeeper check src/requirements.txt --outdated-only --format table || true
      - store_artifacts:
          path: deps-report.json
          destination: deps-report.json

workflows:
  weekly-check:
    triggers:
      - schedule:
          cron: "0 9 * * 1"
          filters:
            branches:
              only:
                - main
    jobs:
      - dependency-check

Pre-commit Hook

Add to .pre-commit-config.yaml:

YAML
repos:
  - repo: local
    hooks:
      - id: depkeeper-check
        name: Check dependencies
        entry: depkeeper check src/requirements.txt --outdated-only --format table
        language: system
        pass_filenames: false
        files: requirements\.txt$

Best Practices

1. Weekly Checks

Schedule dependency checks weekly to stay informed without noise:

YAML
schedule:
  - cron: '0 9 * * 1'  # Monday 9 AM

2. Separate Check and Update

Keep check and update as separate jobs:

  • Check: Always runs, reports status
  • Update: Manual trigger or conditional

3. Test After Updates

Always run your test suite after automated updates:

YAML
- name: Update
  run: depkeeper update src/requirements.txt -y

- name: Install updated packages
  run: pip install -r src/requirements.txt

- name: Test
  run: pytest

4. Create Pull Requests

Don't push directly to main. Create PRs for review:

YAML
- name: Commit and push changes
  run: |
    git config --global user.name "github-actions[bot]"
    git config --global user.email "github-actions[bot]@users.noreply.github.com"
    git checkout -b deps/automated-updates
    git add src/requirements.txt
    git commit -m "chore(deps): update dependencies"
    git push -f origin deps/automated-updates

- name: Create Pull Request
  uses: actions/github-script@v7
  with:
    script: |
      const { data: pulls } = await github.rest.pulls.list({
        owner: context.repo.owner,
        repo: context.repo.repo,
        head: `${context.repo.owner}:deps/automated-updates`,
        state: 'open'
      });

      if (pulls.length === 0) {
        await github.rest.pulls.create({
          owner: context.repo.owner,
          repo: context.repo.repo,
          title: '⬆️ Update dependencies',
          head: 'deps/automated-updates',
          base: 'master',
          body: 'Automated dependency updates by depkeeper.'
        });
      }

Exit Codes

Use exit codes for CI logic:

Code Meaning CI Action
0 Success Continue
1 Error Fail build
2 Usage error Fail build

Next Steps