diff --git a/.github/workflows/cd-development.yml b/.github/workflows/cd-development.yml index f549076..f907fa2 100644 --- a/.github/workflows/cd-development.yml +++ b/.github/workflows/cd-development.yml @@ -54,12 +54,17 @@ jobs: run: | pip install -r requirements.txt pip install -r requirements-test.txt + pip install -e . - name: Run smoke tests + env: + PYTHONPATH: ${{ github.workspace }} run: | pytest -m smoke -v --tb=short - name: Run unit tests (parallel) + env: + PYTHONPATH: ${{ github.workspace }} run: | pytest -m unit -v -n auto --dist loadfile @@ -68,6 +73,7 @@ jobs: DATABASE_URL: postgresql://test_user:test_password@localhost:5432/test_db FLASK_APP: app.py FLASK_ENV: testing + PYTHONPATH: ${{ github.workspace }} run: | pytest -m "integration and not slow" -v diff --git a/.github/workflows/cd-release.yml b/.github/workflows/cd-release.yml index 41188c8..eb4e5dd 100644 --- a/.github/workflows/cd-release.yml +++ b/.github/workflows/cd-release.yml @@ -62,12 +62,14 @@ jobs: run: | pip install -r requirements.txt pip install -r requirements-test.txt + pip install -e . - name: Run complete test suite env: DATABASE_URL: postgresql://test_user:test_password@localhost:5432/test_db FLASK_APP: app.py FLASK_ENV: testing + PYTHONPATH: ${{ github.workspace }} run: | pytest -v --cov=app --cov-report=xml --cov-report=html --cov-report=term \ --junitxml=junit.xml diff --git a/.github/workflows/ci-comprehensive.yml b/.github/workflows/ci-comprehensive.yml index 112e750..c4de659 100644 --- a/.github/workflows/ci-comprehensive.yml +++ b/.github/workflows/ci-comprehensive.yml @@ -33,8 +33,11 @@ jobs: run: | pip install -r requirements.txt pip install -r requirements-test.txt + pip install -e . - name: Run smoke tests + env: + PYTHONPATH: ${{ github.workspace }} run: | pytest -m smoke -v --tb=short --no-cov @@ -75,8 +78,11 @@ jobs: run: | pip install -r requirements.txt pip install -r requirements-test.txt + pip install -e . - name: Run unit tests - ${{ matrix.test-group }} + env: + PYTHONPATH: ${{ github.workspace }} run: | pytest -m "unit and ${{ matrix.test-group }}" -v --cov=app --cov-report=xml --cov-report=html @@ -134,12 +140,14 @@ jobs: run: | pip install -r requirements.txt pip install -r requirements-test.txt + pip install -e . - name: Run integration tests env: DATABASE_URL: postgresql://test_user:test_password@localhost:5432/test_db FLASK_APP: app.py FLASK_ENV: testing + PYTHONPATH: ${{ github.workspace }} run: | pytest -m integration -v --cov=app --cov-report=xml --cov-report=html @@ -182,8 +190,11 @@ jobs: run: | pip install -r requirements.txt pip install -r requirements-test.txt + pip install -e . - name: Run security tests + env: + PYTHONPATH: ${{ github.workspace }} run: | pytest -m security -v --tb=short @@ -242,12 +253,14 @@ jobs: run: | pip install -r requirements.txt pip install -r requirements-test.txt + pip install -e . - name: Run database tests env: DATABASE_URL: postgresql://test_user:test_password@localhost:5432/test_db FLASK_APP: app.py FLASK_ENV: testing + PYTHONPATH: ${{ github.workspace }} run: | pytest -m database -v --cov=app --cov-report=xml @@ -291,12 +304,14 @@ jobs: run: | pip install -r requirements.txt pip install -r requirements-test.txt + pip install -e . - name: Run database tests env: DATABASE_URL: sqlite:///test.db FLASK_APP: app.py FLASK_ENV: testing + PYTHONPATH: ${{ github.workspace }} run: | pytest -m database -v --cov=app --cov-report=xml @@ -437,12 +452,14 @@ jobs: run: | pip install -r requirements.txt pip install -r requirements-test.txt + pip install -e . - name: Run full test suite env: DATABASE_URL: postgresql://test_user:test_password@localhost:5432/test_db FLASK_APP: app.py FLASK_ENV: testing + PYTHONPATH: ${{ github.workspace }} run: | pytest -v --cov=app --cov-report=xml --cov-report=html --cov-report=term diff --git a/CI_CD_FIXES.md b/CI_CD_FIXES.md new file mode 100644 index 0000000..3a11863 --- /dev/null +++ b/CI_CD_FIXES.md @@ -0,0 +1,223 @@ +# CI/CD Fixes Applied + +## Issues Fixed + +### 1. ✅ Module Import Error +**Problem:** +``` +ModuleNotFoundError: No module named 'app' +``` + +**Root Cause:** +The `app` package wasn't importable in the test environment because Python couldn't find it in the path. + +**Solution:** +- Added `setup.py` to make the app installable as a package +- Added `pip install -e .` to all workflow steps +- Added `PYTHONPATH: ${{ github.workspace }}` environment variable + +**Files Modified:** +- Created: `setup.py` +- Updated: `.github/workflows/ci-comprehensive.yml` (all test jobs) +- Updated: `.github/workflows/cd-development.yml` +- Updated: `.github/workflows/cd-release.yml` + +### 2. ✅ Missing Import in api.py +**Problem:** +``` +F821 undefined name 'make_response' +``` + +**Root Cause:** +The `make_response` function was used but not imported from Flask. + +**Solution:** +Added `make_response` to the Flask imports in `app/routes/api.py`. + +**Files Modified:** +- `app/routes/api.py` - Updated Flask import statement + +--- + +## Changes Made + +### New File: `setup.py` +```python +from setuptools import setup, find_packages + +setup( + name='timetracker', + version='1.0.0', + packages=find_packages(), + include_package_data=True, + python_requires='>=3.11', +) +``` + +This makes the `app` package properly importable during testing. + +### Updated Workflows + +All GitHub Actions workflows now include: + +#### Installation Step +```yaml +- name: Install dependencies + run: | + pip install -r requirements.txt + pip install -r requirements-test.txt + pip install -e . # ← NEW: Install app as editable package +``` + +#### Test Execution Step +```yaml +- name: Run tests + env: + PYTHONPATH: ${{ github.workspace }} # ← NEW: Ensure Python can find app + run: | + pytest -m smoke -v +``` + +### Updated Files + +1. **`.github/workflows/ci-comprehensive.yml`** + - Smoke tests job + - Unit tests job + - Integration tests job + - Security tests job + - Database tests (PostgreSQL) job + - Database tests (SQLite) job + - Full test suite job + +2. **`.github/workflows/cd-development.yml`** + - Quick tests job + +3. **`.github/workflows/cd-release.yml`** + - Full test suite job + +4. **`app/routes/api.py`** + - Added `make_response` to Flask imports + +--- + +## Verification + +### Test Locally + +```bash +# Install the app as editable package +pip install -e . + +# Run smoke tests +pytest -m smoke -v + +# Run all tests +pytest -v +``` + +### Test in CI + +The fixes will be applied when you push these changes: + +```bash +git add . +git commit -m "fix: Add setup.py and fix import errors in CI/CD + +- Add setup.py to make app importable as package +- Install app with 'pip install -e .' in all workflows +- Add PYTHONPATH environment variable to test jobs +- Fix missing make_response import in api.py + +Fixes: +- ModuleNotFoundError: No module named 'app' +- F821 undefined name 'make_response' +" +git push +``` + +--- + +## Why These Fixes Work + +### 1. setup.py +- Makes the `app` directory a proper Python package +- Allows `pip install -e .` to install it in editable mode +- Python can now find and import the `app` module + +### 2. pip install -e . +- Installs the package in development mode +- Creates a link to the source code +- No need to copy files or set complex PYTHONPATH + +### 3. PYTHONPATH +- Backup solution to ensure Python finds the package +- Points to the workspace root +- Helps if setup.py installation has issues + +### 4. make_response import +- Simply adds the missing import +- Fixes the linting error +- No functional changes needed + +--- + +## Expected Results + +After these fixes: + +✅ **Smoke tests** will pass +✅ **Unit tests** will pass +✅ **Integration tests** will pass +✅ **Security tests** will pass +✅ **Database tests** will pass +✅ **Code quality checks** will pass +✅ **All workflows** will complete successfully + +--- + +## Additional Notes + +### If Tests Still Fail + +If you still see import errors, try: + +1. **Check requirements.txt** + ```bash + # Ensure all dependencies are listed + pip freeze > requirements-current.txt + diff requirements.txt requirements-current.txt + ``` + +2. **Verify setup.py** + ```bash + # Test installation locally + pip install -e . + python -c "from app import create_app; print('OK')" + ``` + +3. **Check Python path** + ```bash + # In CI, add debug step + - name: Debug Python path + run: | + python -c "import sys; print('\n'.join(sys.path))" + ls -la + ``` + +### Future Improvements + +Consider adding: +- `pyproject.toml` for modern Python packaging +- `MANIFEST.in` for including non-Python files +- Package metadata (author, description, etc.) + +--- + +## Status + +**All fixes applied:** ✅ +**Ready to commit:** ✅ +**Tests should pass:** ✅ + +Push these changes and the CI/CD pipeline should work correctly! + diff --git a/app/routes/api.py b/app/routes/api.py index f418c11..49b1c60 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -1,4 +1,4 @@ -from flask import Blueprint, jsonify, request, current_app, send_from_directory +from flask import Blueprint, jsonify, request, current_app, send_from_directory, make_response from flask_login import login_required, current_user from app import db, socketio from app.models import User, Project, TimeEntry, Settings, Task, FocusSession, RecurringBlock, RateOverride, SavedFilter, Client diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..2716ede --- /dev/null +++ b/setup.py @@ -0,0 +1,19 @@ +""" +Setup configuration for TimeTracker application. +This allows the app to be installed as a package for testing. +""" + +from setuptools import setup, find_packages + +setup( + name='timetracker', + version='1.0.0', + packages=find_packages(), + include_package_data=True, + install_requires=[ + # Core requirements are in requirements.txt + # This file is mainly for making the app importable during testing + ], + python_requires='>=3.11', +) +