Systems Library / Infrastructure / How to Build an Automated Dependency Update System
Infrastructure developer tools

How to Build an Automated Dependency Update System

Keep dependencies updated automatically with security patch notifications.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

Automating dependency updates and security patches keeps your projects safe without the manual chore of checking every package. I run a weekly scan across all my projects. It checks for outdated packages, flags security vulnerabilities, and generates a report I can act on in minutes instead of hours.

What You Need Before Starting

Step 1: Build the Python Dependency Scanner

import subprocess
import json

def scan_python_deps(project_dir):
    result = subprocess.run(
        ["pip", "list", "--outdated", "--format=json"],
        capture_output=True, text=True, cwd=project_dir
    )
    
    try:
        outdated = json.loads(result.stdout)
    except json.JSONDecodeError:
        outdated = []
    
    return [{
        "name": pkg["name"],
        "current": pkg["version"],
        "latest": pkg["latest_version"],
        "type": pkg.get("latest_filetype", "unknown")
    } for pkg in outdated]

def check_vulnerabilities(project_dir):
    result = subprocess.run(
        ["pip", "audit"],
        capture_output=True, text=True, cwd=project_dir
    )
    return {
        "has_vulnerabilities": result.returncode != 0,
        "output": result.stdout[:2000]
    }

Step 2: Build the Node.js Scanner

def scan_node_deps(project_dir):
    result = subprocess.run(
        ["npm", "outdated", "--json"],
        capture_output=True, text=True, cwd=project_dir
    )
    
    try:
        outdated = json.loads(result.stdout)
    except json.JSONDecodeError:
        return []
    
    return [{
        "name": name,
        "current": info.get("current", "unknown"),
        "wanted": info.get("wanted", "unknown"),
        "latest": info.get("latest", "unknown")
    } for name, info in outdated.items()]

def check_node_audit(project_dir):
    result = subprocess.run(
        ["npm", "audit", "--json"],
        capture_output=True, text=True, cwd=project_dir
    )
    
    try:
        audit = json.loads(result.stdout)
        return {
            "vulnerabilities": audit.get("metadata", {}).get("vulnerabilities", {}),
            "total": sum(audit.get("metadata", {}).get("vulnerabilities", {}).values())
        }
    except json.JSONDecodeError:
        return {"vulnerabilities": {}, "total": 0}

Step 3: Scan Multiple Projects

import os

PROJECTS = [
    {"path": "/root/project-a", "type": "python"},
    {"path": "/root/project-b", "type": "node"},
    {"path": "/root/project-c", "type": "python"},
]

def scan_all_projects():
    report = []
    
    for project in PROJECTS:
        name = os.path.basename(project["path"])
        entry = {"name": name, "path": project["path"]}
        
        if project["type"] == "python":
            entry["outdated"] = scan_python_deps(project["path"])
            entry["security"] = check_vulnerabilities(project["path"])
        elif project["type"] == "node":
            entry["outdated"] = scan_node_deps(project["path"])
            entry["security"] = check_node_audit(project["path"])
        
        report.append(entry)
    
    return report

Step 4: Generate the Report

def format_report(report):
    lines = ["Dependency Scan Report", "=" * 40, ""]
    
    for project in report:
        lines.append(f"Project: {project['name']}")
        lines.append(f"  Path: {project['path']}")
        
        outdated = project.get("outdated", [])
        if outdated:
            lines.append(f"  Outdated packages: {len(outdated)}")
            for pkg in outdated[:5]:
                lines.append(f"    {pkg['name']}: {pkg['current']} -> {pkg['latest']}")
            if len(outdated) > 5:
                lines.append(f"    ... and {len(outdated) - 5} more")
        else:
            lines.append("  All packages up to date")
        
        security = project.get("security", {})
        if security.get("has_vulnerabilities") or security.get("total", 0) > 0:
            lines.append("  SECURITY ISSUES FOUND")
        
        lines.append("")
    
    return "\n".join(lines)

Step 5: Alert and Schedule

import requests

def run_dependency_scan():
    report = scan_all_projects()
    formatted = format_report(report)
    
    has_security_issues = any(
        p.get("security", {}).get("has_vulnerabilities") or
        p.get("security", {}).get("total", 0) > 0
        for p in report
    )
    
    if has_security_issues:
        formatted = "SECURITY VULNERABILITIES DETECTED\n\n" + formatted
    
    requests.post("YOUR_SLACK_WEBHOOK", json={"text": f"```\n{formatted}\n```"})

if __name__ == "__main__":
    run_dependency_scan()
# Run weekly on Monday at 9am
0 9 * * 1 python3 /root/tools/dependency_scan.py

What to Build Next

Add auto-update for patch versions. If the update is a patch (1.2.3 to 1.2.4), apply it automatically, run tests, and only alert if tests fail. That handles the low-risk updates without your involvement.

Related Reading

Want this system built for your business?

Get a free assessment. We will map every system your business needs and show you the ROI.

Get Your Free Assessment

Related Systems