Skip to content

Examples

This document provides practical examples of using Zaojun in various scenarios, from simple checks to complex integrations including performance optimization with caching.

Handling a Major Version Bump

Scenario: a major version is available

zaojun
# 💥 django: >=3.2 → Latest: 5.2.1 (major version bump)

💥 means the latest satisfies your spec but crosses a major version boundary — likely has breaking changes. You have three options:

  1. Review and upgrade when ready — use --no-flag-major to suppress 💥 while you're working through the migration, then remove it once you've updated:

    zaojun --no-flag-major
    

  2. Track it without blocking CI — use --major-ok to keep the 💥 signal visible in output but prevent CI from failing on it. Useful when a migration is already on the backlog:

    zaojun --major-ok --cache
    
    Or set it permanently in config:
    [tool.zaojun]
    major-ok = true
    

  3. Pin an upper bound temporarily — add an explicit upper bound to the spec so zaojun no longer sees a compatible major bump:

    django = ">=3.2,<5"   # suppress until ready to migrate
    

Note: packages using full-year CalVer (YYYY.x e.g. black, pip) are automatically excluded from major-bump detection — a year increment is not a breaking-change signal.

Addressing a Known Vulnerability

Scenario: advisory flags a transitive dependency

zaojun reports that requests needs an update, or you receive a GHSA advisory. requests is not in your [project.dependencies] — it's pulled in by another package.

Step 1 — confirm the problem:

zaojun --groups
# ❌ requests: >=2.0 → Latest: 2.33.0

Step 2 — add a constraint in [tool.uv] (not [project.dependencies]):

[tool.uv]
constraint-dependencies = [
    "requests>=2.33.0",  # Addresses vulnerability GHSA-gc5v-m9x4-r6x2
]

Step 3 — re-lock and verify:

uv lock
zaojun --groups
# ✅️ requests>=2.33.0 is up to date

This approach works for any transitive dependency. The constraint only affects your local resolver — it is not visible to consumers of your package.

Scenario: advisory flags a direct dependency

If the vulnerable package is already in [project.dependencies], tighten the lower bound directly:

[project.dependencies]
# Before:
httpx = ">=0.24.0"

# After (GHSA-xxxx fixed in 0.27.0):
httpx = ">=0.27.0"  # Addresses vulnerability GHSA-xxxx-yyyy-zzzz

Always reference the advisory ID in a comment so the constraint remains traceable.

Basic Examples

Check Current Project

# Navigate to your project directory
cd ~/projects/my-python-app

# Check dependencies
zaojun

Check Specific File

# Check dependencies in a specific pyproject.toml
zaojun /path/to/project/pyproject.toml

# Check with a different filename
zaojun requirements.toml

# Check with caching for faster repeated runs
zaojun /path/to/project/pyproject.toml --cache

Minimal Output

# Show only dependencies needing updates
zaojun --short

# Minimal output with caching for performance
zaojun --short --cache

# Output example:
# ⚠️ packaging: ~=23.0 → Latest: 24.0
# ❌ typer: ==0.9.0 → Latest: 1.0.0

Library Mode

Checking a Library's Constraints

# Check that your library's version constraints are consumer-friendly
zaojun --library

# Example output — problems detected:
# ❌ pydantic: exact pin (==2.5.0) blocks consumers
# ❌ httpx: patch-level compatible release (~=0.27.2) is too tight for a library
# ❌ packaging: tight upper bound (<25.0) — use <26 instead
# ⚠️  requests: no version constraint — consumers get no minimum guarantee
# ❌ typer: ~=0.9.0 → Latest: 1.2.0

# Example output — all clean:
# ✅️ pydantic>=2.0 is up to date
# ✅️ httpx~=0.28 is up to date

Library CI Check

# In CI: hygiene + staleness + quarantine + groups
zaojun --library --min-age 7 --groups --cache --short

Comparing Application vs Library Mode

For an application fenliu that uses pydantic:

# Application mode: flags any version not at the latest pinned
zaojun
# ⚠️ pydantic: >=2.0 → Latest: 2.8.0

# Library mode: silent — >=2.0 already covers 2.8.0
zaojun --library
# ✅️ pydantic>=2.0 is up to date

Real-World Scenarios

Development Workflow

# Daily check during development with caching for speed
zaojun --groups --compat-ok --cache --cache-stats

# Before committing changes
zaojun --short --cache

# If updates needed, update dependencies
uv sync -U --all-groups

# Verify updates with fresh cache
zaojun --short --clear-cache --cache

CI/CD Pipeline Integration

GitHub Actions

name: Check Dependencies
on: [push, pull_request]

jobs:
  check-deps:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - name: Install Zaojun
        run: pip install zaojun
      - name: Check dependencies
        run: zaojun --short --groups --no-cache

GitLab CI

check_dependencies:
  image: python:3.11-slim
  script:
    - pip install zaojun
    - zaojun --short --groups --no-cache
  only:
    - merge_requests
    - main

Woodpecker CI

when:
  event: [push, pull_request]

steps:
  check-dependencies:
    image: ghcr.io/astral-sh/uv:debian
    pull: true
    commands:
      - uv --version
      - uv sync --all-groups
      - uv run zaojun --version
      - uv run zaojun --short --groups --no-cache

Jenkins Pipeline

pipeline {
    agent any

    stages {
        stage('Check Dependencies') {
            steps {
                sh 'pip install zaojun'
                sh 'zaojun --short --groups --no-cache'
            }
        }
    }
}

Pre-commit Hook

# .pre-commit-config.yaml
repos:
  - repo: https://codeberg.org/marvin8/zaojun
    rev: 1.2.0  # Use latest version
    hooks:
      - id: zaojun
        args:
          - "--groups"
          - "--compat-ok"  # Don't fail on compatible updates
          - "--cache"      # Enable caching for faster runs

Docker Integration

# Dockerfile for dependency checking
FROM python:3.11-slim

RUN pip install zaojun

WORKDIR /app
COPY pyproject.toml .

CMD ["zaojun", "--groups", "--short", "--cache"]
# Build and run
docker build -t zaojun-checker .
docker run --rm zaojun-checker

Nox Integration

# noxfile.py - Add Zaojun to your Nox sessions
from nox import session

@session
def check_dependencies(session):
    """Check for outdated dependencies using Zaojun."""
    session.install("zaojun")
    # Check main dependencies with caching
    session.run("zaojun", "--compat-ok", "--cache")
    # Check all dependency groups including dev dependencies with caching
    session.run("zaojun", "--groups", "--compat-ok", "--cache")

@session
def ci_checks(session):
    """Run all CI checks including dependency validation."""
    session.install("zaojun", "pytest", "ruff")
    # Format and lint code
    session.run("ruff", "format", ".")
    session.run("ruff", "check", ".")
    # Check dependencies with caching
    session.run("zaojun", "--short", "--cache")
    # Run tests
    session.run("pytest", "tests/")

Run these sessions with:

# Check dependencies only
uv run nox -s check_dependencies

# Run all CI checks
uv run nox -s ci_checks

Supply-Chain Quarantine

Basic quarantine

# Only flag updates that are at least 7 days old
zaojun --min-age 7 --groups

CI with quarantine

# In CI: flag incompatible updates, quarantine anything < 14 days old
zaojun --min-age 14 --short --groups

Combine with caching

# Fast repeated checks, skipping brand-new releases
zaojun --cache --min-age 7 --groups --cache-stats

Advanced Examples

Monitoring Multiple Projects

#!/bin/bash
# check-all-projects.sh

PROJECTS=(
    "/home/user/projects/api"
    "/home/user/projects/web"
    "/home/user/projects/cli"
)

for project in "${PROJECTS[@]}"; do
    echo "=== Checking $project ==="
    cd "$project" && zaojun --short --cache --cache-stats
    echo ""
done

Automated Update Script

#!/bin/bash
# auto-update-deps.sh

# Clear cache for fresh data before update check
zaojun --clear-cache --cache-stats

# Check if updates are needed with caching enabled
zaojun --short --compat-ok --cache
EXIT_CODE=$?

if [ $EXIT_CODE -eq 0 ]; then
    echo "No incompatible updates needed."
    exit 0
fi

# Check what needs updating with cache statistics
echo "The following dependencies need updating:"
zaojun --short --cache-stats

# Ask for confirmation
read -p "Update dependencies? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    echo "Updating dependencies..."
    uv sync -U --all-groups
    echo "Dependencies updated."

    # Clear cache after update to ensure fresh data
    zaojun --clear-cache --cache-stats
else
    echo "Update cancelled."
fi

Integration with Package Managers

Using with uv

# Check dependencies with caching
zaojun --groups --cache --cache-stats

# Update all dependencies
uv sync -U --all-groups

# Verify updates with fresh cache
zaojun --short --clear-cache --cache

Using with pip

# Generate requirements.txt
uv pip compile pyproject.toml --output-file requirements.txt

# Check dependencies in requirements.txt
# (Convert to pyproject.toml format first)
zaojun

Custom Reporting

JSON Output

Use --format json for reliable machine-readable output — no text parsing required:

# Check if any deps need updating (CI-friendly, no text parsing)
if zaojun --format json | jq -e '.needs_update'; then
  echo "Dependencies need updating" && exit 1
fi

# List all packages needing attention
zaojun --format json | jq '.dependencies[] | select(.status != "up_to_date")'

# Get only incompatible updates
zaojun --format json | jq '[.dependencies[] | select(.status == "incompatible_update")]'

# Check with caching enabled
zaojun --cache --format json | jq '.needs_update'

# Check all groups and get JSON
zaojun --groups --format json | jq '{main: .dependencies, groups: .groups}'

Markdown Report

#!/bin/bash
# markdown-report.sh

echo "# Dependency Report"
echo "Generated: $(date)"
echo ""

# Include cache statistics in report
echo "## Cache Statistics"
zaojun --cache-stats --short 2>/dev/null | grep -v "^$" | while read -r line; do
    echo "- $line"
done
echo ""

zaojun --groups --cache | while read -r line; do
    if [[ $line =~ ^Checking\ dependencies\ in ]]; then
        echo "## Main Dependencies"
    elif [[ $line =~ ^Checking\ dependency\ group\ \[(.+)\] ]]; then
        echo ""
        echo "## ${BASH_REMATCH[1]} Dependencies"
    elif [[ $line =~ ^✅️ ]]; then
        echo "- ✅ $(echo "$line" | sed 's/✅️ //')"
    elif [[ $line =~ ^⚠️ ]]; then
        echo "- ⚠️ $(echo "$line" | sed 's/⚠️ //')"
    elif [[ $line =~ ^❌ ]]; then
        echo "- ❌ $(echo "$line" | sed 's/❌ //')"
    fi
done

Integration Examples

With Makefile

.PHONY: check-deps update-deps check-deps-cache

check-deps:
    zaojun --short --groups --no-cache

check-deps-cache:
    zaojun --short --groups --cache --cache-stats

update-deps: check-deps
    @read -p "Update dependencies? (y/n): " choice; \
    if [ "$$choice" = "y" ]; then \
        uv sync -U --all-groups; \
        echo "Dependencies updated."; \
    else \
        echo "Update cancelled."; \
    fi

ci-check:
    zaojun --short --groups --no-cache

With Taskfile

# Taskfile.yml
version: '3'

tasks:
  check-deps:
    desc: Check dependency updates (no cache for CI)
    cmds:
      - zaojun --short --groups --no-cache

  check-deps-dev:
    desc: Check dependency updates with caching (development)
    cmds:
      - zaojun --short --groups --cache --cache-stats

  update-deps:
    desc: Update all dependencies
    cmds:
      - zaojun --short --groups --clear-cache
      - uv sync -U --all-groups

Advanced Woodpecker CI with Nox

# .woodpecker/checks.yml - Complete CI pipeline with Zaojun
when:
  event: [push, pull_request, release]

steps:
  lint-and-test:
    image: ghcr.io/astral-sh/uv:debian
    pull: true
    commands:
      - uv --version
      - uv sync --all-groups
      # Run all nox sessions including dependency checking
      - uv run nox
      # Additional dependency check with short output (no cache for CI consistency)
      - uv run zaojun --short --no-cache

  weekly-audit:
    image: ghcr.io/astral-sh/uv:debian
    pull: true
    when:
      cron: "0 0 * * 1"  # Run every Monday at midnight
    commands:
      - uv sync --all-groups
      # Comprehensive weekly dependency audit with fresh data
      - uv run zaojun --groups --clear-cache --cache-stats
      - uv run nox -s pysentry
      # Generate dependency report
      - uv run zaojun --short --cache > dependency-report.txt
      - cat dependency-report.txt

Python Script Integration

#!/usr/bin/env python3
"""Custom dependency checker using Zaojun API."""

import subprocess
import sys
from pathlib import Path

def check_dependencies(project_path: Path) -> bool:
    """Check dependencies and return True if updates needed."""
    try:
        result = subprocess.run(
            ["zaojun", "--short", "--cache", str(project_path)],
            capture_output=True,
            text=True,
            check=False
        )

        if result.returncode == 1:
            print("Updates needed:")
            print(result.stdout)
            return True
        elif result.returncode == 0:
            print("All dependencies up to date.")
            return False
        else:
            print(f"Error: {result.stderr}")
            return False

    except FileNotFoundError:
        print("Error: zaojun not found. Install with: pip install zaojun")
        return False

if __name__ == "__main__":
    project_path = Path(sys.argv[1]) if len(sys.argv) > 1 else Path.cwd()
    needs_update = check_dependencies(project_path)
    sys.exit(1 if needs_update else 0)

Special Cases

Monorepo Structure

# Check each package in a monorepo with caching
zaojun packages/core/pyproject.toml --cache
zaojun packages/web/pyproject.toml --cache
zaojun packages/cli/pyproject.toml --cache

# Or use a script with caching
find . -name "pyproject.toml" -type f | while read -r file; do
    echo "=== Checking $(dirname "$file") ==="
    zaojun "$file" --short --cache --cache-stats
    echo ""
done

Private Package Indexes

# Zaojun currently only supports PyPI
# For private indexes, you might need to:
# 1. Use a PyPI mirror that includes your private packages
# 2. Or extend Zaojun to support custom indexes

# Note: Caching works with any PyPI-compatible index
zaojun --cache  # Caches responses from whatever index PyPI uses

2. Use a local PyPI mirror

3. Check against a local package database

## Troubleshooting Examples

### Network Issues
```bash
# Check if PyPI is accessible
curl -I https://pypi.org

# Use HTTP proxy if needed
export HTTPS_PROXY="http://proxy.example.com:8080"
zaojun

# Or use HTTP instead of HTTPS (not recommended)
# Note: Zaojun always uses HTTPS for PyPI

Permission Issues

# Install for current user only
pip install --user zaojun

# Or use virtual environment
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
pip install zaojun

Version Conflicts

# Check Zaojun version
zaojun --version

# Upgrade if needed
pip install --upgrade zaojun

# Check Python version
python --version
# Zaojun requires Python 3.11+

Best Practices Examples

Regular Maintenance Schedule

#!/bin/bash
# weekly-check.sh

# Run every Monday
echo "=== Weekly Dependency Check ==="
echo "Date: $(date)"
echo ""

# Check all projects
for project in /home/user/projects/*; do
    if [ -f "$project/pyproject.toml" ]; then
        echo "Checking $project..."
        cd "$project" && zaojun --short --groups
        echo ""
    fi
done

Before Releases

#!/bin/bash
# pre-release-check.sh

echo "=== Pre-release Dependency Check ==="

# Check for any updates
zaojun --groups

# Ask about updating
read -p "Update dependencies before release? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    echo "Updating dependencies..."
    uv sync -U --all-groups

    echo "Running tests..."
    pytest

    echo "Ready for release!"
else
    echo "Proceeding without updates."
fi

Team Collaboration

# Add to team onboarding checklist:
# 1. Install Zaojun: pip install zaojun
# 2. Add pre-commit hook
# 3. Run weekly checks
# 4. Update before major changes

# Share alias in team .bashrc
alias checkdeps='zaojun --groups --compat-ok'
alias depsreport='zaojun --short | sort'

See Also