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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions .bandit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[bandit]
exclude_dirs = tests,migrations,venv,.venv,htmlcov
skips = B101,B601

159 changes: 159 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
name: CI/CD Pipeline

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]

env:
PYTHON_VERSION: '3.11'
POSTGRES_VERSION: '16'

jobs:
lint:
name: Lint and Code Quality
runs-on: ubuntu-latest
steps:
- 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 flake8 black pylint bandit safety

- name: Run Black (code formatting check)
run: black --check app tests

- name: Run Flake8 (linting)
run: flake8 app tests --max-line-length=120 --extend-ignore=E203,W503
continue-on-error: true

- name: Run Pylint
run: pylint app --disable=all --enable=errors --max-line-length=120
continue-on-error: true

- name: Run Bandit (security linting)
run: bandit -r app -f json -o bandit-report.json
continue-on-error: true

- name: Run Safety (dependency vulnerability check)
run: safety check --json
continue-on-error: true

test:
name: Test Suite
runs-on: ubuntu-latest

services:
postgres:
image: postgres:16
env:
POSTGRES_USER: timetracker
POSTGRES_PASSWORD: timetracker
POSTGRES_DB: timetracker_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

steps:
- 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 -r requirements.txt
pip install -r requirements-test.txt

- name: Run database migrations
env:
DATABASE_URL: postgresql+psycopg2://timetracker:timetracker@localhost:5432/timetracker_test
run: |
flask db upgrade

- name: Run tests with coverage
env:
DATABASE_URL: postgresql+psycopg2://timetracker:timetracker@localhost:5432/timetracker_test
FLASK_ENV: testing
SECRET_KEY: test-secret-key-for-ci
run: |
pytest --cov=app --cov-report=xml --cov-report=html --cov-report=term tests/

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false

security:
name: Security Scan
runs-on: ubuntu-latest
steps:
- 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 semgrep

- name: Run Bandit security scan
run: bandit -r app -f json -o bandit-report.json
continue-on-error: true

- name: Run Safety dependency check
run: safety check --json
continue-on-error: true

- name: Run Semgrep security scan
run: semgrep --config=auto app/
continue-on-error: true

build:
name: Docker Build
runs-on: ubuntu-latest
needs: [lint, test]
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v4

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

- name: Login to Docker Hub (if needed)
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME || '' }}
password: ${{ secrets.DOCKER_PASSWORD || '' }}
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
continue-on-error: true

- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: timetracker:latest
cache-from: type=registry,ref=timetracker:latest
cache-to: type=inline

Loading
Loading