Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ jobs:
ruff: ${{ steps.changes.outputs.ruff }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: dorny/paths-filter@v3
id: changes
with:
base: main
filters: |
backend:
- 'backend/**'
Expand Down
346 changes: 346 additions & 0 deletions .github/workflows/depcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,346 @@
# Dependency Check Workflow
# Detects unused and vulnerable dependencies in the project
# Run on: Pull requests and weekly schedule

name: Dependency Check

on:
workflow_dispatch:
inputs:
full_audit:
description: 'Run full audit including all dependencies'
required: false
default: 'false'
type: boolean
schedule:
# Run weekly on Sunday at 3 AM UTC
- cron: '0 3 * * 0'
pull_request:
paths:
- '**/package.json'
- '**/package-lock.json'
- '**/pnpm-lock.yaml'
- '**/requirements*.txt'
- '**/pyproject.toml'
- '.github/workflows/depcheck.yml'

# Cancel in-progress runs for the same branch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
# Detect which parts of the project have changed
changes:
name: Detect Changes
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
frontend: ${{ steps.filter.outputs.frontend }}
backend: ${{ steps.filter.outputs.backend }}
ai-engine: ${{ steps.filter.outputs.ai-engine }}
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Filter paths
id: filter
run: |
echo "Checking for changes in frontend, backend, and ai-engine..."

# Check frontend changes
if git diff --name-only main...HEAD | grep -q "frontend/"; then
echo "frontend=true" >> $GITHUB_OUTPUT
else
echo "frontend=false" >> $GITHUB_OUTPUT
fi

# Check backend changes
if git diff --name-only main...HEAD | grep -q "backend/"; then
echo "backend=true" >> $GITHUB_OUTPUT
else
echo "backend=false" >> $GITHUB_OUTPUT
fi

# Check ai-engine changes
if git diff --name-only main...HEAD | grep -q "ai-engine/"; then
echo "ai-engine=true" >> $GITHUB_OUTPUT
else
echo "ai-engine=false" >> $GITHUB_OUTPUT
fi

echo "Frontend changed: ${{ steps.filter.outputs.frontend }}"
echo "Backend changed: ${{ steps.filter.outputs.backend }}"
echo "AI-Engine changed: ${{ steps.filter.outputs.ai-engine }}"
Comment on lines +43 to +74
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes job checkout does not include fetch-depth: 0, so git diff --name-only main...HEAD will fail because the main ref won't be available in a shallow clone. The CI workflow (ci.yml) correctly uses fetch-depth: 0 for its change detection. Additionally, on schedule and workflow_dispatch (without full_audit) triggers, HEAD is the default branch (main), so main...HEAD will show no changes and all jobs will be skipped — the weekly scheduled scan will never actually run any audits. Consider using fetch-depth: 0 and adding || github.event_name == 'schedule' to the job conditions so scheduled runs audit everything.

Copilot uses AI. Check for mistakes.

# Frontend: depcheck for npm/TypeScript dependencies
depcheck-frontend:
name: Depcheck - Frontend
runs-on: ubuntu-latest
needs: changes
if: ${{ needs.changes.outputs.frontend == 'true' || github.event.inputs.full_audit == 'true' }}
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On schedule trigger runs, github.event.inputs.full_audit is not set (it will be empty/null), so this condition will be false for all three audit jobs when triggered by the weekly schedule. Combined with the change detection issue (which will also output false for scheduled runs), the weekly scan will never actually run any audits. Add || github.event_name == 'schedule' to the if condition of each audit job.

Suggested change
if: ${{ needs.changes.outputs.frontend == 'true' || github.event.inputs.full_audit == 'true' }}
if: ${{ needs.changes.outputs.frontend == 'true' || github.event.inputs.full_audit == 'true' || github.event_name == 'schedule' }}

Copilot uses AI. Check for mistakes.
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '20'
cache: 'pnpm'

- name: Install dependencies
run: |
cd frontend
pnpm install --frozen-lockfile

- name: Run depcheck
id: depcheck
continue-on-error: true
run: |
cd frontend
echo "Running depcheck to find unused dependencies..."

# Run depcheck and capture output
if pnpm depcheck 2>&1; then
echo "✅ No unused dependencies found"
echo "unused_deps_found=false" >> $GITHUB_OUTPUT
else
echo "❌ Unused dependencies detected!"
echo "unused_deps_found=true" >> $GITHUB_OUTPUT
fi

- name: Run npm audit
id: npm-audit
continue-on-error: true
run: |
cd frontend
echo "Running npm audit to check for vulnerabilities..."

# Run npm audit and capture output
if pnpm audit --audit-level=moderate 2>&1 | tee /tmp/npm-audit-output; then
echo "✅ No vulnerabilities found"
echo "vulnerabilities_found=false" >> $GITHUB_OUTPUT
else
echo "❌ Vulnerabilities detected!"
echo "vulnerabilities_found=true" >> $GITHUB_OUTPUT
fi

- name: Report results
if: always()
run: |
if [ "${{ steps.depcheck.outputs.unused_deps_found }}" = "true" ]; then
echo "## ⚠️ Unused Dependencies Detected in Frontend"
echo "depcheck found unused dependencies in the frontend"
echo "Please review and remove unused packages from package.json"
else
echo "✅ Frontend depcheck passed - no unused dependencies"
fi

if [ "${{ steps.npm-audit.outputs.vulnerabilities_found }}" = "true" ]; then
echo "## ⚠️ Vulnerabilities Detected in Frontend"
echo "npm audit found security vulnerabilities"
echo "Please review and update dependencies to fix vulnerabilities"
else
echo "✅ Frontend npm audit passed - no vulnerabilities found"
fi

# Backend: pip-audit for Python dependencies
pip-audit-backend:
name: Pip Audit & Deptree - Backend
runs-on: ubuntu-latest
needs: changes
if: ${{ needs.changes.outputs.backend == 'true' || github.event.inputs.full_audit == 'true' }}
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as the frontend job: on schedule triggers, this condition will always be false because github.event.inputs.full_audit is not available. Add || github.event_name == 'schedule' to ensure the weekly scan runs.

Copilot uses AI. Check for mistakes.
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v6

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

- name: Install pip-audit and pipdeptree
run: |
pip install pip-audit pipdeptree

- name: Run pip-audit and pipdeptree
id: pip-audit
run: |
cd backend
echo "Running pip-audit to check for vulnerabilities and unused dependencies..."

# First, install dependencies
pip install -r requirements.txt -r requirements-dev.txt

# Run pip-audit to check for vulnerabilities
if pip-audit --strict; then
echo "✅ No vulnerabilities found in dependencies"
echo "vulnerabilities_found=false" >> $GITHUB_OUTPUT
else
echo "❌ Vulnerabilities detected in dependencies!"
echo "vulnerabilities_found=true" >> $GITHUB_OUTPUT
fi

# Run pipdeptree to check for unused dependencies
echo ""
echo "Running pipdeptree to check for unused dependencies..."
if pipdeptree --warn fail; then
echo "✅ No unused (undepended) packages found"
echo "unused_deps_found=false" >> $GITHUB_OUTPUT
else
echo "❌ Unused dependencies detected!"
echo "unused_deps_found=true" >> $GITHUB_OUTPUT
fi
Comment on lines +193 to +202
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pipdeptree --warn fail does not detect unused dependencies. It only detects dependency conflicts (version mismatches between installed packages). The step description says "check for unused dependencies" but pipdeptree is not designed for that purpose. For detecting unused Python imports/dependencies, consider tools like deptry which actually analyze source code to find unused dependencies. The current implementation will give a false sense of security regarding unused packages.

Copilot uses AI. Check for mistakes.

- name: Report results
if: always()
run: |
if [ "${{ steps.pip-audit.outputs.vulnerabilities_found }}" = "true" ]; then
echo "## ⚠️ Vulnerabilities Detected in Backend Dependencies"
echo "Please review and update dependencies to fix vulnerabilities"
else
echo "✅ Backend pip-audit passed - no vulnerabilities found"
fi

if [ "${{ steps.pip-audit.outputs.unused_deps_found }}" = "true" ]; then
echo "## ⚠️ Unused Dependencies Detected in Backend"
echo "pipdeptree found packages that are not dependencies of any other package"
echo "Please review and remove unused packages from requirements.txt"
else
echo "✅ Backend pipdeptree passed - no unused dependencies"
fi

# AI-Engine: pip-audit for Python dependencies
pip-audit-ai-engine:
name: Pip Audit & Deptree - AI Engine
runs-on: ubuntu-latest
needs: changes
if: ${{ needs.changes.outputs.ai-engine == 'true' || github.event.inputs.full_audit == 'true' }}
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as the frontend and backend jobs: on schedule triggers, this condition will always be false. Add || github.event_name == 'schedule' to ensure the weekly scan runs.

Suggested change
if: ${{ needs.changes.outputs.ai-engine == 'true' || github.event.inputs.full_audit == 'true' }}
if: ${{ needs.changes.outputs.ai-engine == 'true' || github.event.inputs.full_audit == 'true' || github.event_name == 'schedule' }}

Copilot uses AI. Check for mistakes.
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v6

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

- name: Install pip-audit and pipdeptree
run: |
pip install pip-audit pipdeptree

- name: Run pip-audit and pipdeptree
id: pip-audit-ai
run: |
cd ai-engine
echo "Running pip-audit to check for vulnerabilities and unused dependencies..."

# First, install dependencies
pip install -r requirements.txt -r requirements-dev.txt

# Run pip-audit to check for vulnerabilities
if pip-audit --strict; then
echo "✅ No vulnerabilities found in dependencies"
echo "vulnerabilities_found=false" >> $GITHUB_OUTPUT
else
echo "❌ Vulnerabilities detected in dependencies!"
echo "vulnerabilities_found=true" >> $GITHUB_OUTPUT
fi

# Run pipdeptree to check for unused dependencies
echo ""
echo "Running pipdeptree to check for unused dependencies..."
if pipdeptree --warn fail; then
echo "✅ No unused (undepended) packages found"
echo "unused_deps_found=false" >> $GITHUB_OUTPUT
else
echo "❌ Unused dependencies detected!"
echo "unused_deps_found=true" >> $GITHUB_OUTPUT
fi
Comment on lines +261 to +270
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as in the backend job: pipdeptree --warn fail detects dependency conflicts, not unused dependencies. The comment and output message claiming it checks for "unused dependencies" is misleading.

Copilot uses AI. Check for mistakes.

- name: Report results
if: always()
run: |
if [ "${{ steps.pip-audit-ai.outputs.vulnerabilities_found }}" = "true" ]; then
echo "## ⚠️ Vulnerabilities Detected in AI Engine Dependencies"
echo "Please review and update dependencies to fix vulnerabilities"
else
echo "✅ AI Engine pip-audit passed - no vulnerabilities found"
fi

if [ "${{ steps.pip-audit-ai.outputs.unused_deps_found }}" = "true" ]; then
echo "## ⚠️ Unused Dependencies Detected in AI Engine"
echo "pipdeptree found packages that are not dependencies of any other package"
echo "Please review and remove unused packages from requirements.txt"
else
echo "✅ AI Engine pipdeptree passed - no unused dependencies"
fi

# Summary
dependency-check-summary:
name: Dependency Check Summary
runs-on: ubuntu-latest
needs: [changes, depcheck-frontend, pip-audit-backend, pip-audit-ai-engine]
if: always()
timeout-minutes: 5
steps:
- name: Summary
run: |
echo "## Dependency Check Summary"
echo ""

# Frontend results
echo "### Frontend"
if [ "${{ needs.depcheck-frontend.result }}" == "success" ]; then
echo "✅ Depcheck: Passed"
elif [ "${{ needs.depcheck-frontend.result }}" == "skipped" ]]; then
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shell syntax error: there's an extra closing bracket ]] on this line. elif [ "${{ needs.depcheck-frontend.result }}" == "skipped" ]]; then should be elif [ "${{ needs.depcheck-frontend.result }}" == "skipped" ]; then (single ]). This will cause a bash syntax error and the summary job will fail.

Suggested change
elif [ "${{ needs.depcheck-frontend.result }}" == "skipped" ]]; then
elif [ "${{ needs.depcheck-frontend.result }}" == "skipped" ]; then

Copilot uses AI. Check for mistakes.
echo "⏭️ Depcheck: Skipped (no changes detected)"
else
echo "❌ Depcheck: Failed"
fi
echo ""

# Backend results
echo "### Backend"
if [ "${{ needs.pip-audit-backend.result }}" == "success" ]; then
echo "✅ Pip Audit & Deptree: Passed"
elif [ "${{ needs.pip-audit-backend.result }}" == "skipped" ]; then
echo "⏭️ Pip Audit & Deptree: Skipped (no changes detected)"
else
echo "❌ Pip Audit & Deptree: Failed"
fi
echo ""

# AI-Engine results
echo "### AI Engine"
if [ "${{ needs.pip-audit-ai-engine.result }}" == "success" ]; then
echo "✅ Pip Audit & Deptree: Passed"
elif [ "${{ needs.pip-audit-ai-engine.result }}" == "skipped" ]; then
echo "⏭️ Pip Audit & Deptree: Skipped (no changes detected)"
else
echo "❌ Pip Audit & Deptree: Failed"
fi
echo ""

# Overall status
echo "---"
if [ "${{ needs.depcheck-frontend.result }}" != "failure" ] && \
[ "${{ needs.pip-audit-backend.result }}" != "failure" ] && \
[ "${{ needs.pip-audit-ai-engine.result }}" != "failure" ]; then
echo "🎉 All dependency checks passed!"
exit 0
else
echo "⚠️ Some dependency checks failed. Please review the results above."
exit 1
fi
Loading
Loading