diff --git a/.forgejo/workflows/deploy-backend.yaml b/.forgejo/workflows/deploy-backend.yaml index bb94a58a..110e1a11 100644 --- a/.forgejo/workflows/deploy-backend.yaml +++ b/.forgejo/workflows/deploy-backend.yaml @@ -2,11 +2,9 @@ name: Build and Deploy Backend on: push: - branches: - - dev - paths: - - "Backend/**" - - ".forgejo/workflows/deploy-backend.yaml" + tags: + - "backend-dev-v[0-9]+.[0-9]+.[0-9]+" + - "backend-dev-v[0-9]+.[0-9]+.[0-9]+-*" workflow_dispatch: env: @@ -16,7 +14,6 @@ env: # Docker Image BACKEND_IMAGE_NAME: chamomind/elearning-backend - IMAGE_TAG: ${{ github.event.pull_request.head.sha || github.sha }} # Notifications DISCORD_WEBHOOK_URL: ${{ vars.DISCORD_WEBHOOK_URL }} @@ -26,14 +23,22 @@ jobs: name: Build Backend Docker Image runs-on: ubuntu-latest outputs: - short_sha: ${{ steps.vars.outputs.short_sha }} + version: ${{ steps.version.outputs.version }} steps: - name: Checkout code uses: actions/checkout@v4 - - name: Generate short SHA - id: vars - run: echo "short_sha=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT + - name: Extract version from tag + id: version + run: | + if [[ "${{ github.event_name }}" == "push" ]]; then + # Tag: backend-dev-v1.2.3 → Version: 1.2.3 + VERSION=$(echo "${{ github.ref_name }}" | sed 's/backend-dev-v//g') + echo "version=${VERSION}" >> $GITHUB_OUTPUT + else + # Manual run: use latest-{run_number} + echo "version=latest-${{ github.run_number }}" >> $GITHUB_OUTPUT + fi - name: Log in to Container Registry uses: docker/login-action@v3 @@ -56,9 +61,8 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }} tags: | - type=ref,event=branch - type=sha,prefix= - type=raw,value=latest,enable=${{ github.ref == 'refs/heads/dev' }} + type=raw,value=${{ steps.version.outputs.version }} + type=raw,value=latest,enable=${{ github.event_name == 'push' }} - name: Build and Push Docker image uses: docker/build-push-action@v5 @@ -86,7 +90,7 @@ jobs: script: | cd ~/repo chmod +x ./replace-env.sh ./deploy.sh - ./replace-env.sh BACKEND_TAG "${{ needs.build.outputs.short_sha }}" + ./replace-env.sh BACKEND_TAG "${{ needs.build.outputs.version }}" ./deploy.sh backend notify: diff --git a/.forgejo/workflows/deploy-frontend-learner.yaml b/.forgejo/workflows/deploy-frontend-learner.yaml index 95008c3a..b48b5d2d 100644 --- a/.forgejo/workflows/deploy-frontend-learner.yaml +++ b/.forgejo/workflows/deploy-frontend-learner.yaml @@ -2,11 +2,9 @@ name: Build and Deploy Frontend Learner on: push: - branches: - - dev - paths: - - "Frontend-Learner/**" - - ".forgejo/workflows/deploy-frontend-learner.yaml" + tags: + - "learner-dev-v[0-9]+.[0-9]+.[0-9]+" + - "learner-dev-v[0-9]+.[0-9]+.[0-9]+-*" workflow_dispatch: env: @@ -25,14 +23,22 @@ jobs: name: Build Frontend Learner Docker Image runs-on: ubuntu-latest outputs: - short_sha: ${{ steps.short_sha.outputs.sha }} + version: ${{ steps.version.outputs.version }} steps: - name: Checkout code uses: actions/checkout@v4 - - name: Generate short SHA - id: short_sha - run: echo "sha=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT + - name: Extract version from tag + id: version + run: | + if [[ "${{ github.event_name }}" == "push" ]]; then + # Tag: learner-dev-v1.2.3 → Version: 1.2.3 + VERSION=$(echo "${{ github.ref_name }}" | sed 's/learner-dev-v//g') + echo "version=${VERSION}" >> $GITHUB_OUTPUT + else + # Manual run: use latest-{run_number} + echo "version=latest-${{ github.run_number }}" >> $GITHUB_OUTPUT + fi - name: Log in to Container Registry uses: docker/login-action@v3 @@ -55,9 +61,8 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - type=ref,event=branch - type=sha,prefix= - type=raw,value=latest,enable=${{ github.ref == 'refs/heads/dev' }} + type=raw,value=${{ steps.version.outputs.version }} + type=raw,value=latest,enable=${{ github.event_name == 'push' }} - name: Build and Push Docker image uses: docker/build-push-action@v5 @@ -85,7 +90,7 @@ jobs: script: | cd ~/repo chmod +x ./replace-env.sh ./deploy.sh - ./replace-env.sh FRONTEND_TAG "${{ needs.build.outputs.short_sha }}" + ./replace-env.sh FRONTEND_TAG "${{ needs.build.outputs.version }}" ./deploy.sh learner notify: diff --git a/.forgejo/workflows/deploy-frontend-management.yaml b/.forgejo/workflows/deploy-frontend-management.yaml index 46490b8a..70352ef1 100644 --- a/.forgejo/workflows/deploy-frontend-management.yaml +++ b/.forgejo/workflows/deploy-frontend-management.yaml @@ -2,11 +2,9 @@ name: Build and Deploy Frontend Management to Dev Server on: push: - branches: - - dev - paths: - - "frontend_management/**" - - ".forgejo/workflows/deploy-frontend-management.yaml" + tags: + - "management-dev-v[0-9]+.[0-9]+.[0-9]+" + - "management-dev-v[0-9]+.[0-9]+.[0-9]+-*" workflow_dispatch: env: @@ -25,14 +23,22 @@ jobs: name: Build Frontend Management Docker Image runs-on: ubuntu-latest outputs: - short_sha: ${{ steps.short_sha.outputs.sha }} + version: ${{ steps.version.outputs.version }} steps: - name: Checkout code uses: actions/checkout@v4 - - name: Generate short SHA - id: short_sha - run: echo "sha=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT + - name: Extract version from tag + id: version + run: | + if [[ "${{ github.event_name }}" == "push" ]]; then + # Tag: management-dev-v1.2.3 → Version: 1.2.3 + VERSION=$(echo "${{ github.ref_name }}" | sed 's/management-dev-v//g') + echo "version=${VERSION}" >> $GITHUB_OUTPUT + else + # Manual run: use latest-{run_number} + echo "version=latest-${{ github.run_number }}" >> $GITHUB_OUTPUT + fi - name: Log in to Container Registry uses: docker/login-action@v3 @@ -55,9 +61,8 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - type=ref,event=branch - type=sha,prefix= - type=raw,value=latest,enable=${{ github.ref == 'refs/heads/dev' }} + type=raw,value=${{ steps.version.outputs.version }} + type=raw,value=latest,enable=${{ github.event_name == 'push' }} - name: Build and Push Docker image uses: docker/build-push-action@v5 @@ -85,7 +90,7 @@ jobs: script: | cd ~/repo chmod +x ./replace-env.sh ./deploy.sh - ./replace-env.sh MANAGEMENT_TAG "${{ needs.build.outputs.short_sha }}" + ./replace-env.sh MANAGEMENT_TAG "${{ needs.build.outputs.version }}" ./deploy.sh management notify: diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 00000000..9a05e0dd --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,423 @@ +# 🚀 E-Learning Platform Deployment Guide + +## Overview + +This project uses **tag-based deployment** with semantic versioning. Deployments are triggered by pushing Git tags, not by pushing to branches. + +--- + +## 📋 Prerequisites + +- Git installed and configured +- Access to push tags to the repository +- Understanding of semantic versioning + +--- + +## 🏷️ Tag Naming Convention + +### Format +``` +--v +``` + +### Services +- `backend` - Backend API +- `learner` - Frontend Learner +- `management` - Frontend Management + +### Environments +- `dev` - Development server +- `staging` - Staging server (future) +- `prod` - Production server (future) + +### Version Format (Semantic Versioning) +- **Major.Minor.Patch** (e.g., `1.0.0`) +- **Major.Minor.Patch-PreRelease** (e.g., `1.0.0-beta`, `1.0.0-rc1`) + +### Examples +``` +backend-dev-v1.0.0 +learner-dev-v1.2.3 +management-dev-v2.0.0-beta +``` + +--- + +## 🚀 Deployment Commands + +### 1. Deploy All Services (Same Version) + +Use this when deploying a complete release with all services updated. + +```bash +# Set version +VERSION="1.0.0" + +# Create tags for all services +git tag backend-dev-v${VERSION} +git tag learner-dev-v${VERSION} +git tag management-dev-v${VERSION} + +# Push all tags at once +git push origin --tags + +# Or push individually +git push origin backend-dev-v${VERSION} +git push origin learner-dev-v${VERSION} +git push origin management-dev-v${VERSION} +``` + +--- + +### 2. Deploy Single Service + +Use this when only one service needs to be updated (e.g., hotfix). + +#### Backend Only +```bash +git tag backend-dev-v1.0.1 +git push origin backend-dev-v1.0.1 +``` + +#### Frontend Learner Only +```bash +git tag learner-dev-v1.0.1 +git push origin learner-dev-v1.0.1 +``` + +#### Frontend Management Only +```bash +git tag management-dev-v1.0.1 +git push origin management-dev-v1.0.1 +``` + +--- + +### 3. Deploy Pre-Release Version + +Use this for testing before official release. + +```bash +# Beta release +git tag backend-dev-v1.0.0-beta +git push origin backend-dev-v1.0.0-beta + +# Release candidate +git tag backend-dev-v1.0.0-rc1 +git push origin backend-dev-v1.0.0-rc1 + +# Alpha release +git tag backend-dev-v1.0.0-alpha +git push origin backend-dev-v1.0.0-alpha +``` + +--- + +### 4. View Existing Tags + +```bash +# List all tags +git tag + +# List tags for specific service +git tag | grep backend-dev +git tag | grep learner-dev +git tag | grep management-dev + +# Show tag details +git show backend-dev-v1.0.0 +``` + +--- + +### 5. Delete Tag (If Mistake) + +```bash +# Delete local tag +git tag -d backend-dev-v1.0.0 + +# Delete remote tag +git push origin --delete backend-dev-v1.0.0 +``` + +--- + +## 📝 Complete Deployment Workflow + +### Scenario: Release v1.0.0 + +```bash +# 1. Ensure you're on dev branch and up to date +git checkout dev +git pull origin dev + +# 2. Make your changes +git add . +git commit -m "feat: implement user authentication" +git push origin dev + +# 3. Test locally (optional but recommended) +cd Backend +docker compose up + +# 4. Create version tags +git tag backend-dev-v1.0.0 +git tag learner-dev-v1.0.0 +git tag management-dev-v1.0.0 + +# 5. Push tags to trigger CI/CD +git push origin --tags + +# 6. Monitor CI/CD pipeline +# - Check Forgejo Actions +# - Check Discord notifications +# - Verify deployment on server + +# 7. Verify deployment +curl http://192.168.1.69:20901/health +curl http://192.168.1.69:20902 +curl http://192.168.1.69:20903 +``` + +--- + +### Scenario: Hotfix v1.0.1 (Backend Only) + +```bash +# 1. Fix the bug +git checkout dev +git pull origin dev +git add . +git commit -m "fix: resolve authentication bug" +git push origin dev + +# 2. Create patch version tag (only backend) +git tag backend-dev-v1.0.1 + +# 3. Push tag +git push origin backend-dev-v1.0.1 + +# 4. Only backend will be rebuilt and deployed +# Frontend services remain on v1.0.0 +``` + +--- + +### Scenario: Feature Release v1.1.0 + +```bash +# 1. Develop feature +git checkout dev +git add . +git commit -m "feat: add course filtering" +git push origin dev + +# 2. Create minor version tags +git tag backend-dev-v1.1.0 +git tag learner-dev-v1.1.0 +git tag management-dev-v1.1.0 + +# 3. Push tags +git push origin --tags +``` + +--- + +### Scenario: Breaking Change v2.0.0 + +```bash +# 1. Implement breaking changes +git checkout dev +git add . +git commit -m "feat!: redesign API endpoints (BREAKING CHANGE)" +git push origin dev + +# 2. Create major version tags +git tag backend-dev-v2.0.0 +git tag learner-dev-v2.0.0 +git tag management-dev-v2.0.0 + +# 3. Push tags +git push origin --tags +``` + +--- + +## 🔄 Rollback to Previous Version + +If a deployment fails or has issues, rollback to a previous version: + +### On Server (SSH) + +```bash +# SSH to server +ssh dev@192.168.1.69 + +# Navigate to repo +cd ~/repo + +# Update environment variables to previous version +./replace-env.sh BACKEND_TAG "1.0.0" +./replace-env.sh FRONTEND_TAG "1.0.0" +./replace-env.sh MANAGEMENT_TAG "1.0.0" + +# Redeploy with old version +./deploy.sh backend +./deploy.sh learner +./deploy.sh management +``` + +--- + +## 📊 Version History + +### View Deployment History + +```bash +# List all tags sorted by version +git tag -l "backend-dev-v*" --sort=-v:refname + +# Show commits for a specific tag +git log backend-dev-v1.0.0 -1 + +# Compare versions +git diff backend-dev-v1.0.0 backend-dev-v1.1.0 +``` + +--- + +## 🛠️ Helper Scripts + +### Create Multi-Service Tag Script + +Create `scripts/tag-release.sh`: + +```bash +#!/bin/bash + +if [ -z "$1" ]; then + echo "Usage: ./tag-release.sh " + echo "Example: ./tag-release.sh 1.0.0" + exit 1 +fi + +VERSION=$1 + +echo "Creating tags for version ${VERSION}..." +git tag backend-dev-v${VERSION} +git tag learner-dev-v${VERSION} +git tag management-dev-v${VERSION} + +echo "Tags created:" +git tag | grep "v${VERSION}" + +echo "" +echo "Push tags with: git push origin --tags" +``` + +Usage: +```bash +chmod +x scripts/tag-release.sh +./scripts/tag-release.sh 1.0.0 +git push origin --tags +``` + +--- + +## ⚠️ Important Notes + +> [!IMPORTANT] +> **Pushing to `dev` branch does NOT trigger deployment.** You must create and push a tag to deploy. + +> [!WARNING] +> **Tags are immutable.** Once pushed, a tag should not be changed. If you need to fix a release, create a new patch version. + +> [!TIP] +> **Use pre-release tags for testing.** Tag with `-beta` or `-rc1` suffix to test before official release. + +--- + +## 🔍 Troubleshooting + +### Tag Already Exists +```bash +# Error: tag 'backend-dev-v1.0.0' already exists +# Solution: Use next version number +git tag backend-dev-v1.0.1 +``` + +### CI/CD Not Triggering +```bash +# Check if tag matches pattern +git tag | grep backend-dev-v1.0.0 + +# Verify tag was pushed to remote +git ls-remote --tags origin | grep backend-dev-v1.0.0 +``` + +### Wrong Tag Pushed +```bash +# Delete from remote +git push origin --delete backend-dev-v1.0.0 + +# Delete from local +git tag -d backend-dev-v1.0.0 + +# Create correct tag +git tag backend-dev-v1.0.1 +git push origin backend-dev-v1.0.1 +``` + +--- + +## 📚 Semantic Versioning Guide + +### When to Increment + +| Change Type | Version | Example | +|-------------|---------|---------| +| Bug fix | Patch (x.x.1) | `1.0.0` → `1.0.1` | +| New feature (backward compatible) | Minor (x.1.x) | `1.0.0` → `1.1.0` | +| Breaking change | Major (1.x.x) | `1.0.0` → `2.0.0` | +| Pre-release | Add suffix | `1.0.0-beta` | + +### Examples + +```bash +# Bug fixes +1.0.0 → 1.0.1 → 1.0.2 + +# New features +1.0.0 → 1.1.0 → 1.2.0 + +# Breaking changes +1.0.0 → 2.0.0 → 3.0.0 + +# Pre-releases +1.0.0-alpha → 1.0.0-beta → 1.0.0-rc1 → 1.0.0 +``` + +--- + +## 🎯 Quick Reference + +```bash +# Deploy all services v1.0.0 +git tag backend-dev-v1.0.0 learner-dev-v1.0.0 management-dev-v1.0.0 +git push origin --tags + +# Deploy backend only v1.0.1 +git tag backend-dev-v1.0.1 && git push origin backend-dev-v1.0.1 + +# View tags +git tag | grep dev + +# Delete tag +git tag -d backend-dev-v1.0.0 +git push origin --delete backend-dev-v1.0.0 +``` + +--- + +**Last Updated:** 2026-02-11 diff --git a/compose.yaml b/compose.yaml index 0673f7cf..92b6682a 100644 --- a/compose.yaml +++ b/compose.yaml @@ -5,23 +5,27 @@ services: # Backend API backend: - image: 192.168.1.60/chamomind/elearning-backend:${BACKEND_TAG:-latest} + image: ${GITEA_INSTANCE}/chamomind/elearning-backend:${BACKEND_TAG} container_name: elearning-backend restart: unless-stopped ports: - - "4000:4000" + - "20901:4000" env_file: - .env + environment: + - NODE_ENV=production networks: - elearning-shared # Frontend Learner - frontend-learner: - image: 192.168.1.60/chamomind/elearning-learner:${FRONTEND_TAG:-latest} + learner: + image: ${GITEA_INSTANCE}/chamomind/elearning-learner:${FRONTEND_TAG} container_name: elearning-learner restart: unless-stopped ports: - "20902:3000" + environment: + - PORT=${PORT_MANG:-3000} env_file: - .env depends_on: @@ -30,12 +34,14 @@ services: - elearning-shared # Frontend Management - frontend-management: - image: 192.168.1.60/chamomind/elearning-management:${MANAGEMENT_TAG:-latest} + management: + image: ${GITEA_INSTANCE}/chamomind/elearning-management:${MANAGEMENT_TAG} container_name: elearning-management restart: unless-stopped ports: - "20903:3001" + environment: + - PORT=${PORT_MANG:-3001} env_file: - .env depends_on: