Skip to content

feat(ci): workflows #25

feat(ci): workflows

feat(ci): workflows #25

Workflow file for this run

name: CI
on:
push:
branches: [master, dev, feat/*, fix/*, docs/*, release/*]
pull_request:
branches: [master, dev, feat/*, fix/*, docs/*, release/*]
workflow_dispatch:
jobs:
lint:
name: Code Quality (Linting & Formatting)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "pip"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ruff black isort pydocstyle mypy bandit[toml]
pip install types-PyYAML types-setuptools
pip install -e .
- name: Run Ruff (linting)
run: |
ruff check visdrone_toolkit/ scripts/ tests/ --exit-non-zero-on-fix
- name: Run Ruff (formatting check)
run: |
ruff format --check visdrone_toolkit/ scripts/ tests/
- name: Run Black (formatting check)
run: |
black --check --diff visdrone_toolkit/ scripts/ tests/ --line-length=100
- name: Run isort (import sorting check)
run: |
isort --check-only --diff visdrone_toolkit/ scripts/ tests/ --profile=black --line-length=100
- name: Run pydocstyle (docstring check)
run: |
pydocstyle visdrone_toolkit/ --convention=google --add-ignore=D100,D101,D102,D103,D104,D105,D107,D212
continue-on-error: true
- name: Run mypy (type checking)
run: |
mypy visdrone_toolkit/ --ignore-missing-imports --check-untyped-defs
continue-on-error: true
- name: Run Bandit (security linting)
run: |
bandit -r visdrone_toolkit/ -c pyproject.toml
continue-on-error: true
markdown-yaml-lint:
name: Markdown & YAML Linting
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "18"
- name: Install markdownlint-cli
run: npm install -g markdownlint-cli
- name: Run markdownlint
run: |
markdownlint '**/*.md' --disable MD013 MD033 MD041 --ignore node_modules || true
continue-on-error: true
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install yamllint
run: pip install yamllint
- name: Run yamllint
run: |
yamllint . -d "{extends: default, rules: {line-length: {max: 120}, document-start: disable}}" || true
continue-on-error: true
test:
name: Tests (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11"]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgl1 libglib2.0-0
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
pip install -e ".[dev]"
- name: Run pytest with coverage
run: |
pytest tests/ -v --cov=visdrone_toolkit --cov-report=xml --cov-report=term
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
if: matrix.python-version == '3.10'
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "pip"
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgl1 libglib2.0-0
python -m pip install --upgrade pip
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
pip install -e ".[dev]"
- name: Test format converters
run: |
pytest tests/test_converters.py -v --tb=short
- name: Test dataset loading
run: |
pytest tests/test_dataset.py -v --tb=short
- name: Test model initialization
run: |
pytest tests/test_models.py -v --tb=short || true
continue-on-error: true
pre-commit:
name: Pre-commit Hooks
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
cache: "pip"
- name: Set up Node.js (for prettier, markdownlint)
uses: actions/setup-node@v4
with:
node-version: "18"
- name: Install pre-commit
run: |
python -m pip install --upgrade pip
pip install pre-commit
- name: Cache pre-commit hooks
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Run pre-commit on all files
run: |
pre-commit run --all-files --show-diff-on-failure
continue-on-error: false
build:
name: Build Distribution
runs-on: ubuntu-latest
needs: [lint, test]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build package
run: |
python -m build
- name: Check distribution
run: |
twine check dist/*
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dist-packages
path: dist/
security:
name: Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install safety bandit[toml]
pip install -e .
- name: Run safety (dependency vulnerability check)
run: |
safety check --json || true
continue-on-error: true
- name: Run bandit (security linting)
run: |
bandit -r visdrone_toolkit/ -c pyproject.toml -f json -o bandit-report.json || true
continue-on-error: true
- name: Upload security reports
uses: actions/upload-artifact@v4
if: always()
with:
name: security-reports
path: bandit-report.json
shell-check:
name: Shell Script Linting
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@master
with:
scandir: "./scripts"
severity: warning
continue-on-error: true
docs:
name: Documentation Build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install sphinx sphinx-rtd-theme
pip install -e .
- name: Check README
run: |
if [ ! -f README.md ]; then
README_PATH="README.md"
elif [ -f .github/README.md ]; then
README_PATH=".github/README.md"
else
echo "README.md not found"
exit 1
fi
if [ $(wc -l < "$README_PATH") -lt 50 ]; then
echo "README.md seems too short"
exit 1
fi
echo "✓ README.md found and validated"
- name: Validate CHANGELOG
run: |
if [ -f CHANGELOG.md ]; then
CHANGELOG_PATH="CHANGELOG.md"
elif [ -f .github/CHANGELOG.md ]; then
CHANGELOG_PATH=".github/CHANGELOG.md"
else
echo "CHANGELOG.md not found"
exit 0
fi
if [ $(wc -l < "$CHANGELOG_PATH") -gt 10 ]; then
echo "✓ CHANGELOG.md found"
else
echo "⚠ CHANGELOG.md not found (warning only)"
fi
continue-on-error: true
- name: Check LICENSE
run: |
if [ -f LICENSE ]; then
echo "✓ LICENSE found"
else
echo "✗ LICENSE not found"
exit 1
fi
python-compatibility:
name: Python Syntax Check (Pyupgrade)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install pyupgrade
run: pip install pyupgrade
- name: Check Python 3.8+ syntax
run: |
find visdrone_toolkit/ scripts/ tests/ -name "*.py" -exec pyupgrade --py38-plus {} +
continue-on-error: true
summary:
name: CI Summary
runs-on: ubuntu-latest
needs:
[
lint,
markdown-yaml-lint,
test,
integration-tests,
pre-commit,
build,
security,
shell-check,
docs,
python-compatibility,
]
if: always()
steps:
- name: Check CI status
run: |
echo "Lint: ${{ needs.lint.result }}"
echo "Markdown/YAML Lint: ${{ needs.markdown-yaml-lint.result }}"
echo "Tests: ${{ needs.test.result }}"
echo "Integration Tests: ${{ needs.integration-tests.result }}"
echo "Pre-commit: ${{ needs.pre-commit.result }}"
echo "Build: ${{ needs.build.result }}"
echo "Security: ${{ needs.security.result }}"
echo "Shell Check: ${{ needs.shell-check.result }}"
echo "Docs: ${{ needs.docs.result }}"
echo "Python Compatibility: ${{ needs.python-compatibility.result }}"
- name: Fail if critical jobs failed
if: |
needs.lint.result == 'failure' ||
needs.test.result == 'failure' ||
needs.pre-commit.result == 'failure' ||
needs.build.result == 'failure'
run: |
echo "Critical CI checks failed"
exit 1