Skip to content
Merged
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
185 changes: 185 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
name: CI/CD Pipeline

on:
push:
branches: [ main, develop, 'claude/**' ]
pull_request:
branches: [ main, develop ]
Comment on lines +3 to +7

Choose a reason for hiding this comment

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

P1 Badge Trigger CI on the active work branch

The workflow introduced in this commit only triggers on pushes to main, develop, or claude/** and on PRs targeting main/develop. However, the repository’s current work happens on the work branch (this commit itself is on work), so developers pushing to the branch they actively collaborate on will never get any CI feedback. That defeats the purpose of adding this pipeline because regressions can land on work unchecked until someone happens to open a PR to main. Please include the work branch (or broaden the glob) in both the push and pull_request triggers so every change in this repo actually runs the new checks.

Useful? React with 👍 / 👎.


env:
PYTHON_VERSION: "3.11"

jobs:
code-quality:
name: Code Quality Checks
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt

- name: Run Black (Code Formatting Check)
run: |
black --check --diff app/ domains/ tests/ scripts/

- name: Run Ruff (Linting)
run: |
ruff check app/ domains/ tests/ scripts/

- name: Run mypy (Type Checking)
run: |
mypy app/ domains/ scripts/
continue-on-error: true # Allow failures initially during migration

- name: Check import sorting (isort)
run: |
isort --check-only --diff app/ domains/ tests/ scripts/

test:
name: Run Tests
runs-on: ubuntu-latest
needs: code-quality
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

The needs: code-quality dependency on line 53 creates a serial execution where tests only run after code quality checks pass. This increases total CI time. Since both jobs are independent (both check code but in different ways), consider removing this dependency to allow parallel execution and faster feedback. If code quality fails, the overall CI will still fail, but developers get test results simultaneously.

Suggested change
needs: code-quality

Copilot uses AI. Check for mistakes.

services:
neo4j:
image: neo4j:5.14-community
env:
NEO4J_AUTH: neo4j/testpassword
NEO4J_PLUGINS: '["apoc"]'
ports:
- 7687:7687
- 7474:7474
options: >-
--health-cmd "cypher-shell -u neo4j -p testpassword 'RETURN 1'"
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y tesseract-ocr tesseract-ocr-eng

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt

- name: Wait for Neo4j
run: |
for i in {1..30}; do
if curl -f http://localhost:7474/ > /dev/null 2>&1; then
echo "Neo4j is ready!"
break
fi
echo "Waiting for Neo4j... ($i/30)"
sleep 2
done

- name: Run unit tests
run: |
pytest tests/unit -v --cov=app --cov=domains --cov-report=xml --cov-report=term
env:
NEO4J_URI: bolt://localhost:7687
NEO4J_USER: neo4j
NEO4J_PASSWORD: testpassword

- name: Run service tests
run: |
pytest tests/service -v --cov=app --cov=domains --cov-append --cov-report=xml --cov-report=term
env:
NEO4J_URI: bolt://localhost:7687
NEO4J_USER: neo4j
NEO4J_PASSWORD: testpassword

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: unittests
name: codecov-watchman
fail_ci_if_error: false
continue-on-error: true

docker-build:
name: Docker Build Test
runs-on: ubuntu-latest
needs: test

Comment on lines +130 to +131
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

The needs: test dependency on line 130 creates unnecessary serialization. The Docker build test is independent of test results and could run in parallel with the test job. This would reduce total CI time. Consider removing this dependency to improve CI performance.

Suggested change
needs: test

Copilot uses AI. Check for mistakes.
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: the-watchman:test
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Test Docker Compose configuration
run: |
docker compose config

security:
name: Security Scanning
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install bandit safety

- name: Run Bandit (Security Linting)
run: |
bandit -r app/ domains/ scripts/ -f json -o bandit-report.json
continue-on-error: true

- name: Run Safety (Dependency Vulnerability Check)
run: |
safety check --json
continue-on-error: true
Comment on lines +175 to +178
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

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

The safety check on line 177 may fail in CI without proper authentication. Safety 3.0+ requires an API key for full functionality. Since this is set to continue-on-error: true, failures will be silent. Consider either:

  1. Adding a SAFETY_API_KEY secret to the repository
  2. Downgrading to Safety 2.x in requirements-dev.txt
  3. Removing this check if API key management is not desired

This aligns with the issue identified in requirements-dev.txt regarding Safety version.

Copilot uses AI. Check for mistakes.

- name: Upload Bandit report
uses: actions/upload-artifact@v4
if: always()
with:
name: bandit-report
path: bandit-report.json
95 changes: 95 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Pre-commit hooks for The Watchman project
# Install: pip install pre-commit && pre-commit install
# Run manually: pre-commit run --all-files

repos:
# General file checks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
- id: end-of-file-fixer
- id: check-yaml
args: [--unsafe] # Allow custom tags in docker-compose.yml
- id: check-toml
- id: check-json
- id: check-added-large-files
args: [--maxkb=1000]
- id: check-merge-conflict
- id: check-case-conflict
- id: detect-private-key
- id: mixed-line-ending
args: [--fix=lf]

# Code formatting with Black
- repo: https://github.com/psf/black
rev: 23.12.1
hooks:
- id: black
language_version: python3.11
args: [--line-length=100]

# Import sorting with isort
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
args: [--profile=black, --line-length=100]

# Linting with Ruff (fast Python linter)
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.9
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]

# Type checking with mypy
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
additional_dependencies:
- types-requests
- types-PyYAML
- types-python-dateutil
- pydantic
args: [--ignore-missing-imports, --show-error-codes]
exclude: ^(tests/|scripts/comfy_inventory_watcher.py)

# Security linting with Bandit
- repo: https://github.com/PyCQA/bandit
rev: 1.7.6
hooks:
- id: bandit
args: [-c, pyproject.toml]
additional_dependencies: ["bandit[toml]"]
exclude: ^tests/

# Dockerfile linting
- repo: https://github.com/hadolint/hadolint
rev: v2.12.0
hooks:
- id: hadolint-docker
args: [--ignore, DL3008, --ignore, DL3013]

# Markdown linting
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.38.0
hooks:
- id: markdownlint
args: [--fix]

# YAML linting
- repo: https://github.com/adrienverge/yamllint
rev: v1.33.0
hooks:
- id: yamllint
args: [-c=.yamllint.yml]

# Run on commit by default
default_install_hook_types: [pre-commit, pre-push]
default_stages: [commit]

# Faster parallel execution
fail_fast: false
15 changes: 15 additions & 0 deletions .yamllint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
extends: default

rules:
line-length:
max: 120
level: warning
indentation:
spaces: 2
indent-sequences: true
comments:
min-spaces-from-content: 1
document-start: disable
truthy:
allowed-values: ['true', 'false', 'on', 'off']
Loading
Loading