@@ -432,19 +432,200 @@ The Docker entrypoint ([docker-entrypoint.sh](docker-entrypoint.sh)) automatical
432432- ` storage_data ` - Uploaded book covers
433433- ` vendor ` - Composer dependencies
434434
435+ ## CI/CD & Automated Deployment
436+
437+ The application uses ** GitHub Actions** for automated deployment to production when code is pushed to the ` main ` branch.
438+
439+ ### Deployment Workflow
440+
441+ ** Development → Production Flow:**
442+ 1 . Development happens in ** GitHub Codespaces** (https://silver-space-orbit-xx4x79vwgpcvpp.github.dev/ )
443+ 2 . Developer manually commits and pushes changes to GitHub (` git push ` )
444+ 3 . GitHub Actions automatically triggers deployment
445+ 4 . Production server pulls latest code and restarts containers
446+
447+ ** Automated Deployment Process:**
448+ - Triggered on: ` git push ` to ` main ` branch
449+ - GitHub Actions workflow: [ .github/workflows/deploy.yml] ( .github/workflows/deploy.yml )
450+ - Deployment script: [ deploy.sh] ( deploy.sh ) (runs on production server)
451+ - No manual intervention required after push
452+
453+ ### Production Server Details
454+
455+ ** Server Environment:**
456+ - Provider: Hetzner VM
457+ - User: ` deploy `
458+ - Application directory: ` /opt/leafmark `
459+ - Git repository: Cloned from ` https://github.com/roberteinsle/leafmark.git `
460+
461+ ** Directory Structure:**
462+ ```
463+ /opt/leafmark/
464+ ├── docker-compose.yaml # Docker configuration
465+ ├── Dockerfile # App container build instructions
466+ ├── deploy.sh # Deployment script (executable)
467+ └── [Laravel application files...]
468+ ```
469+
470+ ### Initial Production Setup
471+
472+ ** Prerequisites on Hetzner VM:**
473+ ``` bash
474+ # Install Docker and Docker Compose
475+ curl -fsSL https://get.docker.com -o get-docker.sh
476+ sudo sh get-docker.sh
477+ sudo usermod -aG docker deploy
478+
479+ # Install Git
480+ sudo apt update
481+ sudo apt install -y git
482+ ```
483+
484+ ** Setup deployment user and repository:**
485+ ``` bash
486+ # Login as deploy user
487+ sudo su - deploy
488+
489+ # Create application directory
490+ sudo mkdir -p /opt/leafmark
491+ sudo chown deploy:deploy /opt/leafmark
492+ cd /opt/leafmark
493+
494+ # Clone repository
495+ git clone https://github.com/roberteinsle/leafmark.git .
496+
497+ # Make deployment script executable
498+ chmod +x deploy.sh
499+
500+ # Configure environment (if not already done)
501+ # See "Initial Server Setup" section below for .env configuration
502+ ```
503+
504+ ** Setup GitHub Actions SSH Access:**
505+
506+ 1 . Generate SSH key pair on your local machine:
507+ ``` bash
508+ ssh-keygen -t ed25519 -C " github-actions-deploy" -f ~ /.ssh/leafmark_deploy
509+ ```
510+
511+ 2 . Copy public key to production server:
512+ ``` bash
513+ ssh-copy-id -i ~ /.ssh/leafmark_deploy.pub deploy@YOUR_SERVER_IP
514+ ```
515+
516+ 3 . Add GitHub Secrets (GitHub Repository → Settings → Secrets and variables → Actions):
517+ - ` PROD_HOST ` - Production server IP address
518+ - ` PROD_USER ` - ` deploy `
519+ - ` PROD_SSH_KEY ` - Contents of private key file (` cat ~/.ssh/leafmark_deploy ` )
520+ - ` PROD_SSH_PORT ` - SSH port (usually ` 22 ` )
521+
522+ ** Test SSH connection:**
523+ ``` bash
524+ ssh -i ~ /.ssh/leafmark_deploy deploy@YOUR_SERVER_IP " cd /opt/leafmark && pwd"
525+ ```
526+
527+ ### Deployment Script Details
528+
529+ The [ deploy.sh] ( deploy.sh ) script performs these steps:
530+
531+ 1 . ** Pull latest code** from GitHub (` git pull origin main ` )
532+ 2 . ** Stop containers** (` docker compose down ` )
533+ 3 . ** Rebuild containers** (` docker compose up -d --build ` )
534+ 4 . ** Wait for startup** (10 seconds)
535+ 5 . ** Run migrations** (` php artisan migrate --force ` )
536+ 6 . ** Clear caches** (` config:cache ` , ` route:cache ` , ` view:cache ` )
537+ 7 . ** Verify storage symlink** (` storage:link ` )
538+
539+ ** Key Features:**
540+ - Preserves Docker volumes (database and uploaded files are NOT deleted)
541+ - Automatic migration execution
542+ - Cache clearing for updated routes/config
543+ - Logs deployment timestamp and status
544+
545+ ### Manual Deployment
546+
547+ If you need to deploy manually without pushing to GitHub:
548+
549+ ``` bash
550+ # SSH into production server
551+ ssh deploy@YOUR_SERVER_IP
552+
553+ # Navigate to application directory
554+ cd /opt/leafmark
555+
556+ # Run deployment script
557+ bash deploy.sh
558+ ```
559+
560+ ### Deployment Monitoring
561+
562+ ** View deployment logs in GitHub:**
563+ 1 . Go to repository → Actions tab
564+ 2 . Select the latest workflow run
565+ 3 . View deployment logs and status
566+
567+ ** View application logs on server:**
568+ ``` bash
569+ # SSH into server
570+ ssh deploy@YOUR_SERVER_IP
571+
572+ # View Docker container logs
573+ cd /opt/leafmark
574+ docker compose logs -f app
575+ ```
576+
577+ ### Rollback Procedure
578+
579+ If deployment fails and you need to rollback:
580+
581+ ``` bash
582+ # SSH into production server
583+ ssh deploy@YOUR_SERVER_IP
584+ cd /opt/leafmark
585+
586+ # Check git log for previous commit
587+ git log --oneline -n 5
588+
589+ # Rollback to previous commit (replace COMMIT_HASH)
590+ git reset --hard COMMIT_HASH
591+
592+ # Re-run deployment script
593+ bash deploy.sh
594+ ```
595+
596+ ** ⚠️ WARNING:** Rolling back code does NOT rollback database migrations. If new migrations were run, you may need to manually rollback migrations:
597+ ``` bash
598+ docker compose exec app php artisan migrate:rollback
599+ ```
600+
435601## Production Deployment
436602
603+ ** Note:** This section describes manual production setup. For automated deployment via GitHub Actions, see [ CI/CD & Automated Deployment] ( #cicd--automated-deployment ) .
604+
605+ ** Production Server:**
606+ - Server: Hetzner VM
607+ - User: ` deploy `
608+ - Location: ` /opt/leafmark `
609+ - Automated deployment: Enabled via GitHub Actions
610+
437611### Initial Server Setup
438612
439613``` bash
614+ # Login as deploy user
615+ sudo su - deploy
616+
440617# Create directory and clone repository
441- cd ~ /leafmark
442- git clone https://github.com/roberteinsle/leafmark.git app-source
443- cd app-source
618+ sudo mkdir -p /opt/leafmark
619+ sudo chown deploy:deploy /opt/leafmark
620+ cd /opt/leafmark
621+ git clone https://github.com/roberteinsle/leafmark.git .
444622
445623# Create and configure .env
446624cp .env.example .env
447625nano .env
626+
627+ # Make deployment script executable
628+ chmod +x deploy.sh
448629```
449630
450631** Environment variables are set via docker-compose.yaml:**
@@ -506,10 +687,24 @@ Then configure registration settings:
506687
507688### Update Workflow
508689
509- To update the application:
690+ ** ⚠️ IMPORTANT: ** Updates are now ** automated via GitHub Actions ** . Simply push to ` main ` branch and deployment happens automatically.
510691
692+ ** Automated deployment** (recommended):
693+ 1 . Push changes to GitHub: ` git push origin main `
694+ 2 . GitHub Actions automatically deploys to production
695+ 3 . No manual intervention required
696+
697+ ** Manual deployment** (if needed):
511698``` bash
512- cd ~ /leafmark/app-source
699+ cd /opt/leafmark
700+
701+ # Run deployment script (does everything automatically)
702+ bash deploy.sh
703+ ```
704+
705+ ** Manual step-by-step** (for troubleshooting only):
706+ ``` bash
707+ cd /opt/leafmark
513708
514709# Pull latest code from GitHub
515710git pull origin main
0 commit comments