diff --git a/.github/workflows/cd-development.yml b/.github/workflows/cd-development.yml index 50dfd2ad..b9e3e44a 100644 --- a/.github/workflows/cd-development.yml +++ b/.github/workflows/cd-development.yml @@ -157,6 +157,8 @@ jobs: type=raw,value=develop type=raw,value=dev-{{date 'YYYYMMDD-HHmmss'}} type=sha,prefix=dev-,format=short + labels: | + org.opencontainers.image.description=Self-hosted time tracking web application for projects, clients, and reports. - name: Determine version id: version diff --git a/.github/workflows/cd-release.yml b/.github/workflows/cd-release.yml index 9ec3efb0..2b5797ad 100644 --- a/.github/workflows/cd-release.yml +++ b/.github/workflows/cd-release.yml @@ -365,6 +365,8 @@ jobs: type=semver,pattern={{major}},value=${{ needs.determine-version.outputs.version }} type=raw,value=latest,enable={{is_default_branch}} type=raw,value=stable,enable=${{ needs.determine-version.outputs.is_prerelease == 'false' }} + labels: | + org.opencontainers.image.description=Self-hosted time tracking web application for projects, clients, and reports. - name: Inject analytics configuration from GitHub Secrets env: @@ -1017,16 +1019,16 @@ jobs: working-directory: mobile run: flutter pub get + - name: Generate iOS platform files + working-directory: mobile + run: flutter create --platforms=ios . + - name: Generate launcher icons working-directory: mobile run: | dart run flutter_launcher_icons dart run flutter_launcher_icons -f flutter_launcher_icons_ios.yaml - - name: Generate iOS platform files - working-directory: mobile - run: flutter create --platforms=ios . - - name: Configure iOS project for device build without code signing working-directory: mobile run: | diff --git a/.github/workflows/migration-check.yml b/.github/workflows/migration-check.yml index 1d5fc224..9a57fab2 100644 --- a/.github/workflows/migration-check.yml +++ b/.github/workflows/migration-check.yml @@ -135,21 +135,76 @@ jobs: FLASK_APP: app.py FLASK_ENV: testing run: | + set -e echo "๐Ÿ”„ Testing migration rollback safety..." - # Get current migration - CURRENT_MIGRATION=$(flask db current) + # Get current migration (trim whitespace and optional "(head)" suffix) + CURRENT_MIGRATION=$(flask db current | sed 's/ (head)$//' | tr -d '[:space:]') echo "Current migration: $CURRENT_MIGRATION" - if [ -n "$CURRENT_MIGRATION" ] && [ "$CURRENT_MIGRATION" != "None" ]; then - # Generic rollback test: downgrade one revision, then upgrade back to head - echo "Testing migration rollback (downgrade -1, upgrade head)..." - flask db downgrade -1 - flask db upgrade head - echo "โœ… Migration rollback test passed" - else + if [ -z "$CURRENT_MIGRATION" ] || [ "$CURRENT_MIGRATION" = "None" ]; then echo "โ„น๏ธ No migrations to test rollback on" + exit 0 fi + + # Resolve parent revision via Alembic (avoids ambiguous "downgrade -1" with merge revisions) + ROLLBACK_RESULT=$(python <<'PYEOF' + import os + import sys + from app import create_app, db + from alembic.config import Config + from alembic.script import ScriptDirectory + + app = create_app() + with app.app_context(): + r = db.session.execute(db.text("SELECT version_num FROM alembic_version")) + rows = r.fetchall() + if not rows: + print("SKIP") + sys.exit(0) + current_rev = rows[0][0] + config = Config(os.path.join(os.getcwd(), "migrations", "alembic.ini")) + script = ScriptDirectory.from_config(config) + rev = script.get_revision(current_rev) + if rev is None: + print("SKIP") + sys.exit(0) + down = rev.down_revision + if down is None: + print("SKIP") + elif isinstance(down, tuple): + print("SKIP") + else: + print("PARENT:" + down) + PYEOF + ) + + if [ "$ROLLBACK_RESULT" = "SKIP" ]; then + echo "โ„น๏ธ At base or merge revision โ€” skipping downgrade, verifying upgrade head..." + if ! flask db upgrade head; then + echo "โŒ Rollback test failed: upgrade head failed after skip" + exit 1 + fi + echo "โœ… Migration rollback test passed (downgrade skipped, upgrade head OK)" + exit 0 + fi + + PARENT_REV="${ROLLBACK_RESULT#PARENT:}" + if [ -z "$PARENT_REV" ]; then + echo "โŒ Rollback test failed: could not resolve parent revision" + exit 1 + fi + + echo "Testing migration rollback (downgrade to $PARENT_REV, then upgrade head)..." + if ! flask db downgrade "$PARENT_REV"; then + echo "โŒ Rollback test failed: downgrade to $PARENT_REV failed" + exit 1 + fi + if ! flask db upgrade head; then + echo "โŒ Rollback test failed: upgrade head failed after downgrade" + exit 1 + fi + echo "โœ… Migration rollback test passed" - name: Test migration with sample data if: steps.migration_check.outputs.migration_changes == 'true' diff --git a/.gitignore b/.gitignore index ed7326d0..de361c3f 100644 --- a/.gitignore +++ b/.gitignore @@ -143,6 +143,7 @@ backups/ # IDE .vscode/ .idea/ +.cursor/ *.swp *.swo *~ @@ -167,16 +168,15 @@ bandit-report.json safety-report.json migration_report.md -# Coverage reports -.coverage.* -coverage/ -htmlcov/ -.coverage -coverage.xml - # Test output .testmondata +# Install / build logs +install_log.txt + +# Benchmark output +.benchmarks/ + # SSL Certificates (generated by mkcert) nginx/ssl/*.pem nginx/ssl/*.key @@ -243,9 +243,6 @@ mobile/.flutter-plugins-dependencies.lock.lock.lock.lock.lock.lock.lock.lock mobile/.flutter-plugins-dependencies.lock.lock.lock.lock.lock.lock.lock.lock.lock mobile/.flutter-plugins-dependencies.lock.lock.lock.lock.lock.lock.lock.lock.lock.lock mobile/.flutter-plugins-dependencies.lock.lock.lock.lock.lock.lock.lock.lock.lock.lock.lock -mobile/.android/ - - ## License Files diff --git a/Dockerfile b/Dockerfile index 856cf88c..bc808dd3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,6 +30,7 @@ ENV APP_VERSION=${APP_VERSION} ENV TZ=Europe/Rome # Support visibility: if donate_hide_public.pem is in project root it is copied to /app; set path so app finds it (override in compose if needed) ENV DONATE_HIDE_PUBLIC_KEY_FILE=/app/donate_hide_public.pem +LABEL org.opencontainers.image.description="Self-hosted time tracking web application for projects, clients, and reports." # Install all system dependencies in a single layer RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ diff --git a/INSTALLATION.md b/INSTALLATION.md index 3317cbe0..13fd9242 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -57,7 +57,7 @@ To try TimeTracker without PostgreSQL: ```bash git clone https://github.com/drytrix/TimeTracker.git cd TimeTracker -docker-compose -f docker-compose.local-test.yml up --build +docker-compose -f docker/docker-compose.local-test.yml up --build ``` Then open **http://localhost:8080**. No `.env` is required for this compose file. SQLite is for evaluation only; use PostgreSQL for production. diff --git a/README.md b/README.md index 38c3650a..ab0a98ba 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ TimeTracker is built with modern, reliable technologies: - **flake8** โ€” Linting - **coverage** โ€” Test coverage analysis -**๐Ÿ“– Documentation:** [Architecture overview](ARCHITECTURE.md) ยท [Project Structure](docs/development/PROJECT_STRUCTURE.md) ยท [UI Guidelines](docs/UI_GUIDELINES.md) +**๐Ÿ“– Documentation:** [Architecture overview](docs/ARCHITECTURE.md) ยท [Project Structure](docs/development/PROJECT_STRUCTURE.md) ยท [UI Guidelines](docs/UI_GUIDELINES.md) --- @@ -87,7 +87,7 @@ TimeTracker has been continuously enhanced with powerful new features! Here's wh > **๐Ÿ“‹ For complete release history, see [CHANGELOG.md](CHANGELOG.md)** **Current version** is defined in `setup.py` (single source of truth). See [CHANGELOG.md](CHANGELOG.md) for versioned release history. -- ๐Ÿ“ฑ **Native Mobile & Desktop Apps** โ€” Flutter mobile app (iOS/Android) and Electron desktop app with time tracking, offline support, and API integration ([Build Guide](BUILD.md), [Docs](docs/mobile-desktop-apps/README.md)) +- ๐Ÿ“ฑ **Native Mobile & Desktop Apps** โ€” Flutter mobile app (iOS/Android) and Electron desktop app with time tracking, offline support, and API integration ([Build Guide](docs/build/BUILD.md), [Docs](docs/mobile-desktop-apps/README.md)) - ๐Ÿ“‹ **Project Analysis & Documentation** โ€” Comprehensive project analysis and documentation updates - ๐Ÿ”ง **Version Consistency** โ€” Fixed version inconsistencies across documentation files @@ -288,7 +288,7 @@ TimeTracker includes **130+ features** across 13 major categories. See the [Comp - **Docker Ready** โ€” Deploy in minutes with Docker Compose - **Database Flexibility** โ€” PostgreSQL for production, SQLite for testing - **Responsive Design** โ€” Mobile-first design works perfectly on desktop, tablet, and mobile -- **Native Mobile & Desktop Apps** โ€” Flutter mobile app (iOS/Android) and Electron desktop app with time tracking, offline support, and API integration ([Build Guide](BUILD.md), [Docs](docs/mobile-desktop-apps/README.md)) +- **Native Mobile & Desktop Apps** โ€” Flutter mobile app (iOS/Android) and Electron desktop app with time tracking, offline support, and API integration ([Build Guide](docs/build/BUILD.md), [Docs](docs/mobile-desktop-apps/README.md)) - **Real-time Sync** โ€” WebSocket support for live updates across devices - **Automatic Backups** โ€” Scheduled database backups (configurable) - **Progressive Web App (PWA)** โ€” Install as mobile app with offline support and background sync @@ -466,7 +466,7 @@ git clone https://github.com/drytrix/TimeTracker.git cd TimeTracker # 2. Start with the local test configuration (uses SQLite, no PostgreSQL) -docker-compose -f docker-compose.local-test.yml up --build +docker-compose -f docker/docker-compose.local-test.yml up --build # 3. Access at http://localhost:8080 ``` @@ -592,10 +592,10 @@ Comprehensive documentation is available in the [`docs/`](docs/) directory. See **For Developers:** - **[Contributing](CONTRIBUTING.md)** โ€” How to contribute (quick link) - **[Contributing Guidelines (full)](docs/development/CONTRIBUTING.md)** โ€” Setup, standards, PR process -- **[Development Guide](DEVELOPMENT.md)** โ€” Run locally, test, release process -- **[Architecture](ARCHITECTURE.md)** โ€” System overview and design +- **[Development Guide](docs/DEVELOPMENT.md)** โ€” Run locally, test, release process +- **[Architecture](docs/ARCHITECTURE.md)** โ€” System overview and design - **[Project Structure](docs/development/PROJECT_STRUCTURE.md)** โ€” Codebase layout -- **[API Documentation](API.md)** โ€” API quick reference ยท [Full REST API](docs/api/REST_API.md) +- **[API Documentation](docs/API.md)** โ€” API quick reference ยท [Full REST API](docs/api/REST_API.md) - **[Database Migrations](migrations/README.md)** โ€” Schema management - **[CI/CD Documentation](docs/cicd/CI_CD_DOCUMENTATION.md)** โ€” Build and deployment @@ -629,7 +629,7 @@ Comprehensive documentation is available in the [`docs/`](docs/) directory. See **Integrations & Apps:** - **[Mobile & Desktop Apps](docs/mobile-desktop-apps/README.md)** โ€” Flutter mobile and Electron desktop apps -- **[Build Guide (Mobile & Desktop)](BUILD.md)** โ€” Build scripts for Android, iOS, Windows, macOS, Linux +- **[Build Guide (Mobile & Desktop)](docs/build/BUILD.md)** โ€” Build scripts for Android, iOS, Windows, macOS, Linux - **[Peppol & ZugFerd e-Invoicing](docs/admin/configuration/PEPPOL_EINVOICING.md)** โ€” Peppol sending and ZugFerd/Factur-X PDF embedding (EN 16931) - **[API Documentation](docs/api/REST_API.md)** โ€” REST API reference - **[API Token Scopes](docs/api/API_TOKEN_SCOPES.md)** โ€” Token permissions @@ -697,7 +697,7 @@ docker-compose up -d #### Option 2: Use Pre-built Images ```bash # Use the remote compose file with published images -docker-compose -f docker-compose.remote.yml up -d +docker-compose -f docker/docker-compose.remote.yml up -d ``` > **โš ๏ธ Security Note:** Always set a unique `SECRET_KEY` in production! See [CSRF Configuration](docs/admin/security/CSRF_CONFIGURATION.md) for details. @@ -721,14 +721,16 @@ docker-compose up -d #### Manual HTTPS with mkcert (No Browser Warnings) ```bash # Use mkcert for locally-trusted certificates -docker-compose -f docker-compose.https-mkcert.yml up -d +docker-compose -f docker/docker-compose.https-mkcert.yml up -d ``` -**๐Ÿ“– See [HTTPS Setup Guide](docs/admin/security/README_HTTPS.md) for detailed instructions** +**๐Ÿ“– See [HTTPS Setup Guide](docs/admin/security/README_HTTPS.md) for detailed instructions.** HTTPS helper scripts live in `scripts/` (e.g. from project root: `bash scripts/setup-https-mkcert.sh`, `bash scripts/start-https.sh`). ### Monitoring & Analytics ```bash +# Alternate compose files (local-test, remote, analytics, https) are in docker/; use -f docker/docker-compose.xxx.yml + # Deploy with full monitoring stack (Prometheus, Grafana, Loki) -docker-compose up -d +docker-compose -f docker-compose.yml -f docker/docker-compose.analytics.yml --profile monitoring up -d # Grafana: http://localhost:3000 # Prometheus: http://localhost:9090 ``` @@ -928,7 +930,7 @@ This starts: #### ๐Ÿ“ฑ Native Mobile & Desktop Apps - โœ… **Flutter Mobile App** โ€” Native iOS and Android apps with time tracking, calendar view, offline sync, and API token authentication - โœ… **Electron Desktop App** โ€” Windows, macOS, and Linux desktop app with system tray, time tracking, and offline support -- โœ… **Build Scripts** โ€” Cross-platform build scripts for mobile and desktop ([BUILD.md](BUILD.md)) +- โœ… **Build Scripts** โ€” Cross-platform build scripts for mobile and desktop ([BUILD.md](docs/build/BUILD.md)) #### ๐Ÿ—๏ธ Architecture & Performance - โœ… **Service Layer Migration** โ€” Routes migrated to service layer pattern @@ -959,7 +961,7 @@ We welcome contributions! Whether it's: 2. **Set Up Development Environment** ```bash # Use SQLite for quick local testing - docker-compose -f docker-compose.local-test.yml up -d + docker-compose -f docker/docker-compose.local-test.yml up -d ``` 3. **Make Your Changes** @@ -974,7 +976,7 @@ We welcome contributions! Whether it's: **๐Ÿ“– [CONTRIBUTING.md](CONTRIBUTING.md)** โ€” Quick contributing overview **๐Ÿ“– [Full Contributing Guidelines](docs/development/CONTRIBUTING.md)** โ€” Setup, standards, PR process -**๐Ÿ“– [DEVELOPMENT.md](DEVELOPMENT.md)** โ€” Run locally, tests, releases +**๐Ÿ“– [DEVELOPMENT.md](docs/DEVELOPMENT.md)** โ€” Run locally, tests, releases **๐Ÿ“– [Local Testing with SQLite](docs/development/LOCAL_TESTING_WITH_SQLITE.md)** โ€” Docker SQLite setup ---