diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml deleted file mode 100644 index ea84793..0000000 --- a/.github/workflows/cd.yml +++ /dev/null @@ -1,193 +0,0 @@ -name: CD - Build & Deploy - -on: - push: - branches: [ main ] - tags: - - 'v*' - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -jobs: - build-and-push: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - outputs: - image-tag: ${{ steps.meta.outputs.tags }} - image-version: ${{ steps.meta.outputs.version }} - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Log in to Container Registry - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=sha,prefix={{branch}}- - type=raw,value=latest,enable={{is_default_branch}} - - - name: Build and push Docker image - uses: docker/build-push-action@v4 - with: - context: . - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max - platforms: linux/amd64 - - - name: Image digest - run: echo "Image pushed with digest ${{ steps.build.outputs.digest }}" - - package-helm: - runs-on: ubuntu-latest - needs: build-and-push - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Install Helm - uses: azure/setup-helm@v3 - with: - version: 'latest' - - - name: Package Helm chart - run: | - helm package helm/peikarband --destination . - helm repo index . --url https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }} - - - name: Upload Helm chart artifact - uses: actions/upload-artifact@v3 - with: - name: helm-chart - path: | - *.tgz - index.yaml - - deploy-staging: - runs-on: ubuntu-latest - needs: [build-and-push, package-helm] - if: github.ref == 'refs/heads/main' - environment: - name: staging - url: https://staging.peikarband.ir - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Install kubectl - uses: azure/setup-kubectl@v3 - - - name: Install Helm - uses: azure/setup-helm@v3 - - - name: Configure kubectl - run: | - echo "${{ secrets.KUBECONFIG_STAGING }}" | base64 -d > kubeconfig - export KUBECONFIG=kubeconfig - - - name: Deploy to Staging - run: | - export KUBECONFIG=kubeconfig - helm upgrade --install peikarband-staging ./helm/peikarband \ - --namespace staging \ - --create-namespace \ - --set image.tag=${{ needs.build-and-push.outputs.image-version }} \ - --set image.repository=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} \ - --set ingress.hosts[0].host=staging.peikarband.ir \ - --wait \ - --timeout 5m - - deploy-production: - runs-on: ubuntu-latest - needs: [build-and-push, package-helm] - if: startsWith(github.ref, 'refs/tags/v') - environment: - name: production - url: https://peikarband.ir - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Install kubectl - uses: azure/setup-kubectl@v3 - - - name: Install Helm - uses: azure/setup-helm@v3 - - - name: Configure kubectl - run: | - echo "${{ secrets.KUBECONFIG_PRODUCTION }}" | base64 -d > kubeconfig - export KUBECONFIG=kubeconfig - - - name: Deploy to Production - run: | - export KUBECONFIG=kubeconfig - helm upgrade --install peikarband-prod ./helm/peikarband \ - --namespace production \ - --create-namespace \ - --set image.tag=${{ needs.build-and-push.outputs.image-version }} \ - --set image.repository=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} \ - --set replicaCount=3 \ - --set autoscaling.enabled=true \ - --values helm/peikarband/values-production.yaml \ - --wait \ - --timeout 10m - - - name: Verify deployment - run: | - export KUBECONFIG=kubeconfig - kubectl rollout status deployment/peikarband-prod -n production - kubectl get pods -n production - - release: - runs-on: ubuntu-latest - needs: [build-and-push, package-helm, deploy-production] - if: startsWith(github.ref, 'refs/tags/v') - permissions: - contents: write - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Download Helm chart - uses: actions/download-artifact@v3 - with: - name: helm-chart - - - name: Create Release - uses: softprops/action-gh-release@v1 - with: - files: | - *.tgz - index.yaml - generate_release_notes: true - draft: false - prerelease: false - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 7313779..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,121 +0,0 @@ -name: CI - -on: - push: - branches: [ main, develop ] - pull_request: - branches: [ main, develop ] - -jobs: - test: - runs-on: ubuntu-latest - - strategy: - matrix: - python-version: ['3.11', '3.12'] - - services: - postgres: - image: postgres:14 - env: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - POSTGRES_DB: peikarband_test - ports: - - 5432:5432 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - - redis: - image: redis:7 - ports: - - 6379:6379 - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - - steps: - - uses: actions/checkout@v3 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - - name: Cache pip packages - uses: actions/cache@v3 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements-dev.txt - - - name: Lint with flake8 - run: | - flake8 src/ --count --select=E9,F63,F7,F82 --show-source --statistics - flake8 src/ --count --max-complexity=10 --max-line-length=120 --statistics - - - name: Type check with mypy - run: | - mypy src/ - - - name: Check formatting with black - run: | - black --check src/ - - - name: Check imports with isort - run: | - isort --check-only src/ - - - name: Run tests with pytest - env: - DATABASE_URL: postgresql://postgres:postgres@localhost:5432/peikarband_test - REDIS_URL: redis://localhost:6379/0 - SECRET_KEY: test-secret-key - JWT_SECRET_KEY: test-jwt-secret - CELERY_BROKER_URL: redis://localhost:6379/1 - CELERY_RESULT_BACKEND: redis://localhost:6379/2 - run: | - pytest tests/ -v --cov=src --cov-report=xml --cov-report=term-missing - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 - with: - file: ./coverage.xml - fail_ci_if_error: false - - security: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.11' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install bandit safety - - - name: Run Bandit security scan - run: | - bandit -r src/ -f json -o bandit-report.json || true - - - name: Run Safety check - run: | - safety check --json || true - diff --git a/.gitignore b/.gitignore index c8b4f92..03f8355 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ __pycache__/ *$py.class *.so .Python -build/ develop-eggs/ dist/ downloads/ @@ -27,6 +26,9 @@ venv/ env/ ENV/ +# Local data directory +peikarband/data/ + # Reflex .web/ .reflex/ diff --git a/.woodpecker-back.yml b/.woodpecker-back.yml new file mode 100644 index 0000000..c604e23 --- /dev/null +++ b/.woodpecker-back.yml @@ -0,0 +1,704 @@ +# Woodpecker CI/CD Pipeline - Peikarband Landing +# Application build pipeline (uses pre-built base image) + +variables: + - &python_image 'python:3.11-slim' + - &helm_image 'alpine/helm:latest' + - &base_image 'hub.peikarband.ir/peikarband/base:latest' + +when: + - event: [push, pull_request, tag, manual] + +pipeline: + # ============================================ + # Stage 1: Check Base Image Availability + # ============================================ + + check-base-image: + image: alpine:latest + commands: + - apk add --no-cache curl + - | + echo "Checking if base image is available..." + REGISTRY="hub.peikarband.ir" + REPO="peikarband/base" + TAG="latest" + + if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \ + "https://$REGISTRY/v2/$REPO/manifests/$TAG" > /dev/null 2>&1; then + echo "✓ Base image found: $REGISTRY/$REPO:$TAG" + else + echo "❌ Base image not found!" + echo "Please run .woodpecker-base.yml pipeline first to build base image" + echo "Or trigger it manually in Woodpecker UI" + exit 1 + fi + secrets: [HARBOR_USERNAME, HARBOR_PASSWORD] + when: + - event: [push, tag] + + # ============================================ + # Stage 2: Build Application Image + # ============================================ + + build-image: + image: woodpeckerci/plugin-docker-buildx + settings: + registry: hub.peikarband.ir + repo: hub.peikarband.ir/peikarband/landing + username: + from_secret: HARBOR_USERNAME + password: + from_secret: HARBOR_PASSWORD + + dockerfile: docker/Dockerfile + context: . + platforms: linux/amd64 + + # استفاده از base image + build_args: + - BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest + - VERSION=${CI_COMMIT_SHA:0:8} + - BUILD_DATE=${CI_PIPELINE_CREATED} + + # فقط build می‌کنیم، بدون push + tags: + - ${CI_COMMIT_SHA:0:8} + + labels: + - org.opencontainers.image.created=${CI_PIPELINE_CREATED} + - org.opencontainers.image.source=${CI_REPO_LINK} + - org.opencontainers.image.url=${CI_REPO_LINK} + - org.opencontainers.image.revision=${CI_COMMIT_SHA} + - org.opencontainers.image.version=${CI_COMMIT_SHA:0:8} + - org.opencontainers.image.title=Peikarband Landing + - org.opencontainers.image.description=Peikarband hosting platform landing page + + cache_from: type=registry,ref=hub.peikarband.ir/peikarband/landing:buildcache + cache_to: type=inline + provenance: false + + # فقط build، بدون push + push: false + load: false + + when: + - event: [push, tag] + branch: [main, develop] + + # ============================================ + # Stage 3: Push Image with Multi-Tags + # ============================================ + + push-image: + image: woodpeckerci/plugin-docker-buildx + settings: + registry: hub.peikarband.ir + repo: hub.peikarband.ir/peikarband/landing + username: + from_secret: HARBOR_USERNAME + password: + from_secret: HARBOR_PASSWORD + + dockerfile: docker/Dockerfile + context: . + platforms: linux/amd64 + + build_args: + - BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest + - VERSION=${CI_COMMIT_SHA:0:8} + - BUILD_DATE=${CI_PIPELINE_CREATED} + + # Multi-tagging strategy + tags: + - latest + - ${CI_COMMIT_SHA:0:8} + - ${CI_COMMIT_BRANCH} + + labels: + - org.opencontainers.image.created=${CI_PIPELINE_CREATED} + - org.opencontainers.image.source=${CI_REPO_LINK} + - org.opencontainers.image.url=${CI_REPO_LINK} + - org.opencontainers.image.revision=${CI_COMMIT_SHA} + - org.opencontainers.image.version=${CI_COMMIT_SHA:0:8} + - org.opencontainers.image.title=Peikarband Landing + - org.opencontainers.image.description=Peikarband hosting platform landing page + + cache_from: type=registry,ref=hub.peikarband.ir/peikarband/landing:buildcache + cache_to: type=inline + provenance: false + + # حالا push می‌کنیم + push: true + + when: + - event: [push, tag] + branch: [main, develop] + + # ============================================ + # Stage 4: Verify Push + # ============================================ + + verify-push: + image: alpine:latest + commands: + - apk add --no-cache curl + - | + echo "Verifying image was pushed successfully..." + sleep 3 # Wait for registry sync + + REGISTRY="hub.peikarband.ir" + REPO="peikarband/landing" + TAG="${CI_COMMIT_SHA:0:8}" + + if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \ + "https://$REGISTRY/v2/$REPO/manifests/$TAG" > /dev/null 2>&1; then + echo "✓ Image verified: $REGISTRY/$REPO:$TAG" + else + echo "❌ Failed to verify image push" + exit 1 + fi + secrets: [HARBOR_USERNAME, HARBOR_PASSWORD] + when: + - event: [push, tag] + branch: [main, develop] + + # ============================================ + # Stages below are commented for now + # Uncomment when ready to use + # ============================================ + + # # ============================================ + # # Stage 1: Code Quality & Linting + # # ============================================ + + # lint-flake8: + # image: *python_image + # commands: + # - pip install --no-cache-dir flake8 + # - cd peikarband + # - flake8 src/ --count --select=E9,F63,F7,F82 --show-source --statistics + # - flake8 src/ --count --max-complexity=10 --max-line-length=120 --statistics --exit-zero + # when: + # - event: [push, pull_request, tag] + + # lint-black: + # image: *python_image + # commands: + # - pip install --no-cache-dir black + # - cd peikarband + # - black --check src/ || echo "⚠️ Black formatting issues found (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # lint-isort: + # image: *python_image + # commands: + # - pip install --no-cache-dir isort + # - cd peikarband + # - isort --check-only src/ || echo "⚠️ Import sorting issues found (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # type-check: + # image: *python_image + # commands: + # - pip install --no-cache-dir mypy types-redis types-requests + # - cd peikarband + # - mypy src/ --config-file=config/mypy.ini || echo "⚠️ Type checking issues found (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # # ============================================ + # # Stage 2: Security Scanning + # # ============================================ + + # security-bandit: + # image: *python_image + # commands: + # - pip install --no-cache-dir bandit[toml] + # - cd peikarband + # - bandit -r src/ -f json -o bandit-report.json || true + # - bandit -r src/ -ll || echo "⚠️ Security issues found (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # security-safety: + # image: *python_image + # commands: + # - pip install --no-cache-dir safety + # - cd peikarband + # - safety check -r requirements.txt --json || echo "⚠️ Dependency vulnerabilities found (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # # ============================================ + # # Stage 3: Testing + # # ============================================ + + # test: + # image: *python_image + # commands: + # - apt-get update && apt-get install -y --no-install-recommends curl + # - pip install --no-cache-dir -r peikarband/requirements.txt + # - pip install --no-cache-dir -r peikarband/requirements-dev.txt + # - cd peikarband + # - pytest tests/ -v --cov=src --cov-report=term-missing --cov-report=xml || echo "⚠️ Tests failed (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # # ============================================ + # # Stage 4: Helm Validation + # # ============================================ + + # helm-lint: + # image: *helm_image + # commands: + # - helm version + # - helm lint helm/peikarband + # - echo "✓ Helm chart validation passed" + # when: + # - event: [push, pull_request, tag] + + # helm-template: + # image: *helm_image + # commands: + # - helm template peikarband helm/peikarband -f helm/peikarband/values-production.yaml --debug > /dev/null + # - echo "✓ Helm template rendering successful" + # when: + # - event: [push, pull_request, tag] + + # # ============================================ + # # Stage 6: Deployment - Staging + # # ============================================ + + # deploy-staging: + # image: *helm_image + # commands: + # - apk add --no-cache kubectl + # - echo "$KUBECONFIG_STAGING" | base64 -d > /tmp/kubeconfig + # - export KUBECONFIG=/tmp/kubeconfig + # - | + # helm upgrade --install peikarband-staging helm/peikarband \ + # --namespace staging \ + # --create-namespace \ + # --set image.repository=hub.peikarband.ir/peikarband/landing \ + # --set image.tag=${CI_COMMIT_SHA:0:8} \ + # --set image.pullPolicy=Always \ + # --values helm/peikarband/values-staging.yaml \ + # --wait \ + # --timeout 5m + # - kubectl get pods -n staging + # - echo "✓ Deployed to staging successfully" + # secrets: [KUBECONFIG_STAGING] + # when: + # - event: push + # branch: [main, develop] + + # # ============================================ + # # Stage 7: Deployment - Production + # # ============================================ + + # deploy-production: + # image: *helm_image + # commands: + # - apk add --no-cache kubectl + # - echo "$KUBECONFIG_PRODUCTION" | base64 -d > /tmp/kubeconfig + # - export KUBECONFIG=/tmp/kubeconfig + # - | + # helm upgrade --install peikarband helm/peikarband \ + # --namespace production \ + # --create-namespace \ + # --set image.repository=hub.peikarband.ir/peikarband/landing \ + # --set image.tag=${CI_COMMIT_TAG} \ + # --set image.pullPolicy=Always \ + # --values helm/peikarband/values-production.yaml \ + # --wait \ + # --timeout 10m + # - kubectl rollout status deployment/peikarband -n production + # - kubectl get pods -n production + # - echo "✓ Deployed to production successfully" + # secrets: [KUBECONFIG_PRODUCTION] + # when: + # - event: tag + # ref: refs/tags/v* + + # # ============================================ + # # Stage 8: Notifications + # # ============================================ + + # notify-success: + # image: alpine:latest + # commands: + # - echo "🎉 Pipeline completed successfully!" + # - echo "Branch: ${CI_COMMIT_BRANCH}" + # - echo "Commit: ${CI_COMMIT_SHA:0:8}" + # - echo "Image: hub.peikarband.ir/peikarband/landing:${CI_COMMIT_SHA:0:8}" + # when: + # - event: [push, tag] + # status: success + + # notify-failure: + # image: alpine:latest + # commands: + # - echo "❌ Pipeline failed!" + # - echo "Branch: ${CI_COMMIT_BRANCH}" + # - echo "Commit: ${CI_COMMIT_SHA:0:8}" + # - echo "Please check the logs above" + # when: + # - event: [push, tag] + # status: failure + + + + # Woodpecker CI/CD Pipeline - Peikarband Landing +# Application build pipeline (uses pre-built base image) + +variables: + - &python_image 'python:3.11-slim' + - &helm_image 'alpine/helm:latest' + - &base_image 'hub.peikarband.ir/peikarband/base:latest' + +when: + - event: [push, pull_request, tag, manual] + +pipeline: + # ============================================ + # Stage 1: Check Base Image Availability + # ============================================ + + check-base-image: + image: alpine:latest + commands: + - apk add --no-cache curl + - | + echo "Checking if base image is available..." + REGISTRY="hub.peikarband.ir" + REPO="peikarband/base" + TAG="latest" + + if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \ + "https://$REGISTRY/v2/$REPO/manifests/$TAG" > /dev/null 2>&1; then + echo "✓ Base image found: $REGISTRY/$REPO:$TAG" + else + echo "❌ Base image not found!" + echo "Please run .woodpecker-base.yml pipeline first to build base image" + echo "Or trigger it manually in Woodpecker UI" + exit 1 + fi + secrets: [HARBOR_USERNAME, HARBOR_PASSWORD] + when: + - event: [push, tag] + + # ============================================ + # Stage 2: Build Application Image + # ============================================ + + build-image: + image: woodpeckerci/plugin-docker-buildx + settings: + registry: hub.peikarband.ir + repo: hub.peikarband.ir/peikarband/landing + username: + from_secret: HARBOR_USERNAME + password: + from_secret: HARBOR_PASSWORD + + dockerfile: docker/Dockerfile + context: . + platforms: linux/amd64 + + # استفاده از base image + build_args: + - BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest + - VERSION=${CI_COMMIT_SHA:0:8} + - BUILD_DATE=${CI_PIPELINE_CREATED} + + # فقط build می‌کنیم، بدون push + tags: + - ${CI_COMMIT_SHA:0:8} + + labels: + - org.opencontainers.image.created=${CI_PIPELINE_CREATED} + - org.opencontainers.image.source=${CI_REPO_LINK} + - org.opencontainers.image.url=${CI_REPO_LINK} + - org.opencontainers.image.revision=${CI_COMMIT_SHA} + - org.opencontainers.image.version=${CI_COMMIT_SHA:0:8} + - org.opencontainers.image.title=Peikarband Landing + - org.opencontainers.image.description=Peikarband hosting platform landing page + + cache_from: type=registry,ref=hub.peikarband.ir/peikarband/landing:buildcache + cache_to: type=inline + provenance: false + + # فقط build، بدون push + push: false + load: false + + when: + - event: [push, tag] + branch: [main, develop] + + # ============================================ + # Stage 3: Push Image with Multi-Tags + # ============================================ + + push-image: + image: woodpeckerci/plugin-docker-buildx + settings: + registry: hub.peikarband.ir + repo: hub.peikarband.ir/peikarband/landing + username: + from_secret: HARBOR_USERNAME + password: + from_secret: HARBOR_PASSWORD + + dockerfile: docker/Dockerfile + context: . + platforms: linux/amd64 + + build_args: + - BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest + - VERSION=${CI_COMMIT_SHA:0:8} + - BUILD_DATE=${CI_PIPELINE_CREATED} + + # Multi-tagging strategy + tags: + - latest + - ${CI_COMMIT_SHA:0:8} + - ${CI_COMMIT_BRANCH} + + labels: + - org.opencontainers.image.created=${CI_PIPELINE_CREATED} + - org.opencontainers.image.source=${CI_REPO_LINK} + - org.opencontainers.image.url=${CI_REPO_LINK} + - org.opencontainers.image.revision=${CI_COMMIT_SHA} + - org.opencontainers.image.version=${CI_COMMIT_SHA:0:8} + - org.opencontainers.image.title=Peikarband Landing + - org.opencontainers.image.description=Peikarband hosting platform landing page + + cache_from: type=registry,ref=hub.peikarband.ir/peikarband/landing:buildcache + cache_to: type=inline + provenance: false + + # حالا push می‌کنیم + push: true + + when: + - event: [push, tag] + branch: [main, develop] + + # ============================================ + # Stage 4: Verify Push + # ============================================ + + verify-push: + image: alpine:latest + commands: + - apk add --no-cache curl + - | + echo "Verifying image was pushed successfully..." + sleep 3 # Wait for registry sync + + REGISTRY="hub.peikarband.ir" + REPO="peikarband/landing" + TAG="${CI_COMMIT_SHA:0:8}" + + if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \ + "https://$REGISTRY/v2/$REPO/manifests/$TAG" > /dev/null 2>&1; then + echo "✓ Image verified: $REGISTRY/$REPO:$TAG" + else + echo "❌ Failed to verify image push" + exit 1 + fi + secrets: [HARBOR_USERNAME, HARBOR_PASSWORD] + when: + - event: [push, tag] + branch: [main, develop] + + # ============================================ + # Stages below are commented for now + # Uncomment when ready to use + # ============================================ + + # # ============================================ + # # Stage 1: Code Quality & Linting + # # ============================================ + + # lint-flake8: + # image: *python_image + # commands: + # - pip install --no-cache-dir flake8 + # - cd peikarband + # - flake8 src/ --count --select=E9,F63,F7,F82 --show-source --statistics + # - flake8 src/ --count --max-complexity=10 --max-line-length=120 --statistics --exit-zero + # when: + # - event: [push, pull_request, tag] + + # lint-black: + # image: *python_image + # commands: + # - pip install --no-cache-dir black + # - cd peikarband + # - black --check src/ || echo "⚠️ Black formatting issues found (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # lint-isort: + # image: *python_image + # commands: + # - pip install --no-cache-dir isort + # - cd peikarband + # - isort --check-only src/ || echo "⚠️ Import sorting issues found (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # type-check: + # image: *python_image + # commands: + # - pip install --no-cache-dir mypy types-redis types-requests + # - cd peikarband + # - mypy src/ --config-file=config/mypy.ini || echo "⚠️ Type checking issues found (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # # ============================================ + # # Stage 2: Security Scanning + # # ============================================ + + # security-bandit: + # image: *python_image + # commands: + # - pip install --no-cache-dir bandit[toml] + # - cd peikarband + # - bandit -r src/ -f json -o bandit-report.json || true + # - bandit -r src/ -ll || echo "⚠️ Security issues found (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # security-safety: + # image: *python_image + # commands: + # - pip install --no-cache-dir safety + # - cd peikarband + # - safety check -r requirements.txt --json || echo "⚠️ Dependency vulnerabilities found (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # # ============================================ + # # Stage 3: Testing + # # ============================================ + + # test: + # image: *python_image + # commands: + # - apt-get update && apt-get install -y --no-install-recommends curl + # - pip install --no-cache-dir -r peikarband/requirements.txt + # - pip install --no-cache-dir -r peikarband/requirements-dev.txt + # - cd peikarband + # - pytest tests/ -v --cov=src --cov-report=term-missing --cov-report=xml || echo "⚠️ Tests failed (non-blocking)" + # when: + # - event: [push, pull_request, tag] + + # # ============================================ + # # Stage 4: Helm Validation + # # ============================================ + + # helm-lint: + # image: *helm_image + # commands: + # - helm version + # - helm lint helm/peikarband + # - echo "✓ Helm chart validation passed" + # when: + # - event: [push, pull_request, tag] + + # helm-template: + # image: *helm_image + # commands: + # - helm template peikarband helm/peikarband -f helm/peikarband/values-production.yaml --debug > /dev/null + # - echo "✓ Helm template rendering successful" + # when: + # - event: [push, pull_request, tag] + + # # ============================================ + # # Stage 6: Deployment - Staging + # # ============================================ + + # deploy-staging: + # image: *helm_image + # commands: + # - apk add --no-cache kubectl + # - echo "$KUBECONFIG_STAGING" | base64 -d > /tmp/kubeconfig + # - export KUBECONFIG=/tmp/kubeconfig + # - | + # helm upgrade --install peikarband-staging helm/peikarband \ + # --namespace staging \ + # --create-namespace \ + # --set image.repository=hub.peikarband.ir/peikarband/landing \ + # --set image.tag=${CI_COMMIT_SHA:0:8} \ + # --set image.pullPolicy=Always \ + # --values helm/peikarband/values-staging.yaml \ + # --wait \ + # --timeout 5m + # - kubectl get pods -n staging + # - echo "✓ Deployed to staging successfully" + # secrets: [KUBECONFIG_STAGING] + # when: + # - event: push + # branch: [main, develop] + + # # ============================================ + # # Stage 7: Deployment - Production + # # ============================================ + + # deploy-production: + # image: *helm_image + # commands: + # - apk add --no-cache kubectl + # - echo "$KUBECONFIG_PRODUCTION" | base64 -d > /tmp/kubeconfig + # - export KUBECONFIG=/tmp/kubeconfig + # - | + # helm upgrade --install peikarband helm/peikarband \ + # --namespace production \ + # --create-namespace \ + # --set image.repository=hub.peikarband.ir/peikarband/landing \ + # --set image.tag=${CI_COMMIT_TAG} \ + # --set image.pullPolicy=Always \ + # --values helm/peikarband/values-production.yaml \ + # --wait \ + # --timeout 10m + # - kubectl rollout status deployment/peikarband -n production + # - kubectl get pods -n production + # - echo "✓ Deployed to production successfully" + # secrets: [KUBECONFIG_PRODUCTION] + # when: + # - event: tag + # ref: refs/tags/v* + + # # ============================================ + # # Stage 8: Notifications + # # ============================================ + + # notify-success: + # image: alpine:latest + # commands: + # - echo "🎉 Pipeline completed successfully!" + # - echo "Branch: ${CI_COMMIT_BRANCH}" + # - echo "Commit: ${CI_COMMIT_SHA:0:8}" + # - echo "Image: hub.peikarband.ir/peikarband/landing:${CI_COMMIT_SHA:0:8}" + # when: + # - event: [push, tag] + # status: success + + # notify-failure: + # image: alpine:latest + # commands: + # - echo "❌ Pipeline failed!" + # - echo "Branch: ${CI_COMMIT_BRANCH}" + # - echo "Commit: ${CI_COMMIT_SHA:0:8}" + # - echo "Please check the logs above" + # when: + # - event: [push, tag] + # status: failure + diff --git a/.woodpecker-base.yml b/.woodpecker-base.yml new file mode 100644 index 0000000..2785b01 --- /dev/null +++ b/.woodpecker-base.yml @@ -0,0 +1,142 @@ +# Woodpecker Pipeline - Base Image Builder +# +# این pipeline فقط برای ساخت base image است +# Trigger: Manual یا زمانی که Dockerfile.base تغییر کند +# +# Usage: +# Manual: در Woodpecker UI -> Manual trigger +# Auto: هر بار که docker/Dockerfile.base تغییر کند + +when: + - event: [manual, push] + path: + - docker/Dockerfile.base + - .woodpecker-base.yml + +pipeline: + # ============================================ + # Check if base image needs rebuild + # ============================================ + + check-base-exists: + image: alpine:latest + commands: + - apk add --no-cache curl jq + - | + echo "Checking if base image exists in registry..." + REGISTRY="hub.peikarband.ir" + REPO="peikarband/base" + TAG="python3.11-node20" + + # Try to check if image exists (will fail if doesn't exist) + if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \ + "https://$REGISTRY/v2/$REPO/manifests/$TAG" > /dev/null 2>&1; then + echo "✓ Base image exists: $REGISTRY/$REPO:$TAG" + echo "BASE_EXISTS=true" >> /tmp/base_status + else + echo "⚠️ Base image not found, will build new one" + echo "BASE_EXISTS=false" >> /tmp/base_status + fi + secrets: [HARBOR_USERNAME, HARBOR_PASSWORD] + + # ============================================ + # Build Base Image + # ============================================ + + build-base: + image: woodpeckerci/plugin-docker-buildx + settings: + registry: hub.peikarband.ir + repo: hub.peikarband.ir/peikarband/base + username: + from_secret: HARBOR_USERNAME + password: + from_secret: HARBOR_PASSWORD + + dockerfile: docker/Dockerfile.base + context: . + platforms: linux/amd64 + + # Multi-tag strategy + tags: + - latest + - python3.11-node20 + - python3.11-node20-${CI_COMMIT_SHA:0:8} + + build_args: + - PYTHON_VERSION=3.11 + - NODE_VERSION=20 + + labels: + - org.opencontainers.image.created=${CI_PIPELINE_CREATED} + - org.opencontainers.image.source=${CI_REPO_LINK} + - org.opencontainers.image.revision=${CI_COMMIT_SHA} + - org.opencontainers.image.version=python3.11-node20 + - org.opencontainers.image.title=Peikarband Base Image + - org.opencontainers.image.description=Base image with Python 3.11, Node.js 20, bun + + provenance: false + push: true + + when: + - event: [manual, push] + + # ============================================ + # Verify Base Image + # ============================================ + + verify-base: + image: alpine:latest + commands: + - apk add --no-cache curl + - | + echo "Verifying base image was pushed successfully..." + sleep 5 # Wait for registry to sync + + REGISTRY="hub.peikarband.ir" + REPO="peikarband/base" + TAG="latest" + + if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \ + "https://$REGISTRY/v2/$REPO/manifests/$TAG" > /dev/null 2>&1; then + echo "✓ Base image verified: $REGISTRY/$REPO:$TAG" + echo "✓ Base image is ready for use in application builds" + else + echo "❌ Failed to verify base image" + exit 1 + fi + secrets: [HARBOR_USERNAME, HARBOR_PASSWORD] + when: + - event: [manual, push] + + # ============================================ + # Notification + # ============================================ + + notify-complete: + image: alpine:latest + commands: + - | + echo "================================================" + echo "🎉 Base Image Build Complete!" + echo "================================================" + echo "" + echo "📦 Image Details:" + echo " Registry: hub.peikarband.ir/peikarband/base" + echo " Tags: latest, python3.11-node20, python3.11-node20-${CI_COMMIT_SHA:0:8}" + echo "" + echo "✓ Python: 3.11" + echo "✓ Node.js: 20" + echo "✓ Bun: latest" + echo "✓ Build tools: gcc, g++, make" + echo "" + echo "📝 Next Steps:" + echo " 1. Application builds will now use this base image" + echo " 2. Build time will be significantly faster" + echo " 3. Network reliability improved (no repeated npm/bun installs)" + echo "" + echo "================================================" + when: + - event: [manual, push] + status: success + diff --git a/.woodpecker.yml b/.woodpecker.yml index e51099c..25a2870 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,30 +1,90 @@ +# Woodpecker CI/CD Pipeline - Peikarband Landing +# Smart pipeline with base image management + +variables: + - &base_image 'hub.peikarband.ir/peikarband/landing:base' + - &app_image 'hub.peikarband.ir/peikarband/landing' + +when: + - event: [push, pull_request, tag, manual] pipeline: - publish_landing: + # ============================================ + # Ensure Base Image Exists + # ============================================ + + ensure-base-image: image: woodpeckerci/plugin-docker-buildx settings: - # تنظیمات ریجیستری Harbor registry: hub.peikarband.ir - repo: hub.peikarband.ir/peikarband/landing + repo: *app_image username: from_secret: HARBOR_USERNAME password: from_secret: HARBOR_PASSWORD - # تگ‌گذاری + dockerfile: docker/Dockerfile.base + context: . + platforms: linux/amd64 + + tags: + - base + - base-python3.11-node20 + + build_args: + - PYTHON_VERSION=3.11 + - NODE_VERSION=20 + - BUILD_DATE=${CI_PIPELINE_CREATED} + - VERSION=${CI_COMMIT_SHA:0:8} + + labels: + - org.opencontainers.image.created=${CI_PIPELINE_CREATED} + - org.opencontainers.image.source=${CI_REPO_LINK} + - org.opencontainers.image.title=Peikarband Base + - org.opencontainers.image.description=Base image with Python, Node.js, bun, and build tools + + pull: true + provenance: false + sbom: false + push: true + + + when: + event: [push, tag, manual] + branch: [main, develop, feature/restructure-project] + # Only rebuild base if its definition changed + path: + include: + - docker/Dockerfile.base + - .woodpecker.yml + + # ============================================ + # Build Application Image + # ============================================ + + build-and-push-app: + image: woodpeckerci/plugin-docker-buildx + settings: + registry: hub.peikarband.ir + repo: *app_image + username: + from_secret: HARBOR_USERNAME + password: + from_secret: HARBOR_PASSWORD + + dockerfile: docker/Dockerfile + context: . + platforms: linux/amd64 + + build_args: + - BASE_IMAGE=*base_image + - VERSION=${CI_COMMIT_SHA:0:8} + - BUILD_DATE=${CI_PIPELINE_CREATED} + tags: - latest - ${CI_COMMIT_SHA:0:8} - - dockerfile: Dockerfile - context: . - platforms: linux/amd64 - - build_args: - - VERSION=${CI_COMMIT_SHA:0:8} - - BUILD_DATE=${CI_PIPELINE_CREATED} - - PYTHON_VERSION=3.11 - - NODE_VERSION=20 + - ${CI_COMMIT_BRANCH} labels: - org.opencontainers.image.created=${CI_PIPELINE_CREATED} @@ -35,12 +95,102 @@ pipeline: - org.opencontainers.image.title=Peikarband Landing - org.opencontainers.image.description=Peikarband hosting platform landing page - cache: inline - provenance: true - push: true - + pull: true + provenance: false + sbom: false + push: true + when: - - event: [push, tag, manual] - branch: main # معمولاً فقط روی برنچ اصلی پوش انجام می‌شود + event: [push, tag] + branch: [main, develop, feature/restructure-project] - timeout: 30m \ No newline at end of file + # ============================================ + # Verify Images + # ============================================ + + verify-images: + image: alpine:latest + commands: + - apk add --no-cache curl + - | + echo "════════════════════════════════════════" + echo " 🔍 Verifying Images in Registry" + echo "════════════════════════════════════════" + echo "" + + # Check base image + echo "Checking base image..." + if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \ + "https://hub.peikarband.ir/v2/peikarband/landing/manifests/base" > /dev/null 2>&1; then + echo "✅ Base image: hub.peikarband.ir/peikarband/landing:base" + else + echo "⚠️ Base image not found (this is OK if first build)" + fi + + echo "" + + # Check app image + echo "Checking app image..." + TAG="${CI_COMMIT_SHA:0:8}" + if curl -f -u "$HARBOR_USERNAME:$HARBOR_PASSWORD" \ + "https://hub.peikarband.ir/v2/peikarband/landing/manifests/$TAG" > /dev/null 2>&1; then + echo "✅ App image: hub.peikarband.ir/peikarband/landing:$TAG" + echo "" + echo "Available tags:" + echo " • latest" + echo " • ${CI_COMMIT_SHA:0:8}" + echo " • ${CI_COMMIT_BRANCH}" + echo "" + echo "════════════════════════════════════════" + else + echo "❌ Failed to verify app image" + exit 1 + fi + + secrets: [HARBOR_USERNAME, HARBOR_PASSWORD] + when: + event: [push, tag] + branch: [main, develop, feature/restructure-project] + + # ============================================ + # Notifications + # ============================================ + + notify-success: + image: alpine:latest + commands: + - echo "════════════════════════════════════════" + - echo " 🎉 Pipeline Completed Successfully!" + - echo "════════════════════════════════════════" + - echo "" + - echo "Branch:" "${CI_COMMIT_BRANCH}" + - echo "Commit:" "${CI_COMMIT_SHA:0:8}" + - echo "" + - echo "Images:" + - echo " • Base:" "hub.peikarband.ir/peikarband/landing:base" + - echo " • App:" "hub.peikarband.ir/peikarband/landing:${CI_COMMIT_SHA:0:8}" + - echo "" + - echo "Deploy with:" + - echo " kubectl set image deployment/peikarband-landing \\" + - echo " peikarband-landing=hub.peikarband.ir/peikarband/landing:${CI_COMMIT_SHA:0:8}" + - echo "" + - echo "════════════════════════════════════════" + when: + event: [push, tag] + status: success + + notify-failure: + image: alpine:latest + commands: + - echo "════════════════════════════════════════" + - echo " ❌ Pipeline Failed!" + - echo "════════════════════════════════════════" + - echo "" + - echo "Branch:" "${CI_COMMIT_BRANCH}" + - echo "Commit:" "${CI_COMMIT_SHA:0:8}" + - echo "" + - echo "Please check the logs above" + - echo "════════════════════════════════════════" + when: + event: [push, tag] + status: failure diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index eb02497..0000000 --- a/Dockerfile +++ /dev/null @@ -1,172 +0,0 @@ -# Peikarband Platform - Production Dockerfile -# Multi-stage build for optimized image size and security - -# Build arguments -ARG PYTHON_VERSION=3.11 -ARG NODE_VERSION=20 -ARG VERSION=latest -ARG BUILD_DATE - -# ============================================ -# Stage 1: Builder -# ============================================ -FROM python:${PYTHON_VERSION}-slim AS builder - -# Re-declare ARGs for this stage -ARG NODE_VERSION=20 -ARG VERSION=latest -ARG BUILD_DATE - -LABEL maintainer="Peikarband Team " -LABEL org.opencontainers.image.title="Peikarband Landing" -LABEL org.opencontainers.image.description="Peikarband hosting platform landing page" -LABEL org.opencontainers.image.version="${VERSION}" -LABEL org.opencontainers.image.created="${BUILD_DATE}" - -WORKDIR /build - -# Install build dependencies -RUN apt-get update && apt-get install -y --no-install-recommends \ - gcc \ - g++ \ - make \ - curl \ - gnupg \ - ca-certificates \ - unzip \ - && rm -rf /var/lib/apt/lists/* - -# Install Node.js (required for Reflex) -RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - \ - && apt-get install -y --no-install-recommends nodejs \ - && rm -rf /var/lib/apt/lists/* - -# Install bun (required by Reflex for frontend build) -# Retry mechanism for network issues -RUN set -ex && \ - for i in 1 2 3 4 5; do \ - curl -fsSL https://bun.sh/install | bash && break || \ - (echo "Attempt $i failed, retrying in 5 seconds..." && sleep 5); \ - done || (echo "Failed to install bun after 5 attempts" && exit 1) - -# Add bun to PATH -ENV PATH="/root/.bun/bin:${PATH}" - -# Copy only requirements first (for better layer caching) -COPY requirements.txt . - -# Install Python dependencies in user space -RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \ - pip install --no-cache-dir --user -r requirements.txt - -# Copy application code (excluding .dockerignore items) -COPY --chown=root:root . . - -# Build and export Reflex app for production -# Note: API_URL will be updated at runtime from environment variable -# Export creates .web directory with frontend static files -# bun is now pre-installed, so reflex export won't try to download it -RUN python -m reflex export --no-zip - -# Aggressive cleanup to reduce layer size -# NOTE: Keep .web directory - it contains frontend static files -RUN set -ex && \ - # Remove Python cache - find /build -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true && \ - find /build -type f -name "*.pyc" -delete && \ - find /build -type f -name "*.pyo" -delete && \ - # Remove development files - rm -rf /build/tests /build/docs /build/scripts && \ - rm -rf /build/.git /build/.github /build/.vscode && \ - rm -rf /build/venv /build/env && \ - # Remove node_modules but KEEP .web (frontend static files) - rm -rf /build/node_modules && \ - # Remove large duplicate assets from root - rm -f /build/*.gif /build/*.mp4 /build/*.mov 2>/dev/null || true && \ - # Keep only necessary configs - find /build -type f -name "docker-compose*.yml" -delete && \ - find /build -type f -name "Makefile" -delete - -# ============================================ -# Stage 2: Runtime -# ============================================ -FROM python:${PYTHON_VERSION}-slim - -# Re-declare ARGs for this stage -ARG PYTHON_VERSION=3.11 -ARG VERSION=latest -ARG BUILD_DATE - -# Build info -ENV VERSION=${VERSION} \ - BUILD_DATE=${BUILD_DATE} - -WORKDIR /app - -# Install runtime dependencies only -RUN apt-get update && apt-get install -y --no-install-recommends \ - curl \ - ca-certificates \ - tini \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean - -# Install Node.js runtime -ARG NODE_VERSION=20 -RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - \ - && apt-get install -y --no-install-recommends nodejs \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean - -# Create non-root user first -RUN groupadd -r -g 1000 peikarband && \ - useradd -r -u 1000 -g peikarband -m -s /bin/bash peikarband && \ - mkdir -p /app/logs /app/uploads /app/.reflex - -# Copy Python dependencies from builder to user home -COPY --from=builder /root/.local /home/peikarband/.local - -# Copy application code from builder -COPY --from=builder /build /app - -# Copy and set up runtime script -COPY --chown=peikarband:peikarband scripts/update-env-json.sh /app/scripts/update-env-json.sh -RUN chmod +x /app/scripts/update-env-json.sh - -# Fix ownership -RUN chown -R peikarband:peikarband /home/peikarband/.local /app - -# Add version info (must be before USER switch) -RUN echo "${VERSION}" > /app/.version && \ - chown peikarband:peikarband /app/.version - -# Security: Remove unnecessary setuid/setgid permissions -RUN find / -perm /6000 -type f -exec chmod a-s {} \; 2>/dev/null || true - -# Set environment variables -ENV PATH=/home/peikarband/.local/bin:$PATH \ - PYTHONUNBUFFERED=1 \ - PYTHONDONTWRITEBYTECODE=1 \ - PYTHONHASHSEED=random \ - PIP_NO_CACHE_DIR=1 \ - PIP_DISABLE_PIP_VERSION_CHECK=1 \ - REFLEX_ENV=prod \ - ENVIRONMENT=prod - -# Switch to non-root user -USER peikarband - -# Expose ports -EXPOSE 3000 8000 - -# Health check with better error handling -HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ - CMD curl -f -s -o /dev/null -w "%{http_code}" http://localhost:8000/ping | grep -q "200" || exit 1 - -# Use tini as init system for proper signal handling -# Update .web/env.json from API_URL env var, then run the app -ENTRYPOINT ["/usr/bin/tini", "--", "/app/scripts/update-env-json.sh"] - -# Run application (both frontend and backend) -CMD ["python", "-m", "reflex", "run", "--env", "prod"] - diff --git a/Makefile b/Makefile index 7fb0b58..23c1d94 100644 --- a/Makefile +++ b/Makefile @@ -10,33 +10,58 @@ DOCKER_BUILDKIT ?= 1 .PHONY: help install dev kill-dev test lint format clean docker-up docker-down migrate help: - @echo "Available commands:" + @echo "════════════════════════════════════════" + @echo " 📋 Peikarband Landing - Available Commands" + @echo "════════════════════════════════════════" @echo "" - @echo "Development:" + @echo "🔧 Development:" @echo " make install - Install dependencies" @echo " make dev - Run development server" - @echo " make kill-dev - Kill development server processes (ports 3000 & 8000)" + @echo " make kill-dev - Kill development server (ports 3000 & 8000)" @echo " make test - Run tests" @echo " make lint - Run linters" @echo " make format - Format code" @echo " make clean - Clean temporary files" @echo "" - @echo "Docker:" - @echo " make docker-build - Build Docker image" - @echo " make docker-push - Push Docker image" + @echo "🐳 Docker - Base Image:" + @echo " make docker-build-base - Build base image (Python + Node.js + bun)" + @echo " make docker-push-base - Push base image to Harbor" + @echo "" + @echo "🐳 Docker - Application:" + @echo " make docker-build - Build application image" + @echo " make docker-push - Push application image to Harbor" + @echo " make docker-login - Login to Harbor registry" @echo " make docker-up - Start Docker Compose" @echo " make docker-down - Stop Docker Compose" @echo "" - @echo "Kubernetes/Helm:" + @echo "☸️ Kubernetes/Helm:" @echo " make helm-lint - Lint Helm chart" @echo " make helm-package - Package Helm chart" @echo " make helm-install - Install Helm chart" @echo " make helm-upgrade - Upgrade Helm chart" @echo " make helm-uninstall - Uninstall Helm chart" - @echo " make k8s-deploy - Deploy to Kubernetes" + @echo " make k8s-deploy - Full deployment pipeline" @echo "" - @echo "Database:" + @echo "🗄️ Database:" @echo " make migrate - Run database migrations" + @echo " make seed - Seed database with initial data" + @echo "" + @echo "════════════════════════════════════════" + @echo " Quick Start:" + @echo "════════════════════════════════════════" + @echo "" + @echo "1️⃣ Build & Push Base (once):" + @echo " make docker-login" + @echo " make docker-build-base" + @echo " make docker-push-base" + @echo "" + @echo "2️⃣ Build & Push App:" + @echo " make docker-build" + @echo " make docker-push" + @echo "" + @echo "3️⃣ Deploy:" + @echo " make k8s-deploy" + @echo "" install: pip install -r requirements.txt @@ -44,7 +69,7 @@ install: pre-commit install dev: - python3 -m reflex run + cd peikarband && python3 -m reflex run kill-dev: @echo "Killing processes on ports 3000 and 8000..." @@ -73,32 +98,73 @@ clean: find . -type d -name ".mypy_cache" -exec rm -rf {} + find . -type d -name "*.egg-info" -exec rm -rf {} + rm -rf .coverage htmlcov/ - rm -rf dist/ build/ + rm -rf dist/ # Docker commands +docker-build-base: + @echo "════════════════════════════════════════" + @echo " 🔨 Building Base Image" + @echo "════════════════════════════════════════" + DOCKER_BUILDKIT=$(DOCKER_BUILDKIT) docker buildx build \ + -f docker/Dockerfile.base \ + -t hub.peikarband.ir/peikarband/landing:base \ + -t hub.peikarband.ir/peikarband/landing:base-python3.11-node20 \ + --build-arg PYTHON_VERSION=3.11 \ + --build-arg NODE_VERSION=20 \ + --platform linux/amd64 \ + --load \ + . + @echo "" + @echo "✅ Base image built: hub.peikarband.ir/peikarband/landing:base" + @echo "" + +docker-push-base: + @echo "════════════════════════════════════════" + @echo " 📤 Pushing Base Image" + @echo "════════════════════════════════════════" + docker push hub.peikarband.ir/peikarband/landing:base + docker push hub.peikarband.ir/peikarband/landing:base-python3.11-node20 + @echo "" + @echo "✅ Base image pushed successfully!" + @echo "" + docker-build: - DOCKER_BUILDKIT=$(DOCKER_BUILDKIT) docker build \ - -t $(IMAGE_NAME):$(VERSION) \ - -t $(IMAGE_NAME):latest \ + @echo "════════════════════════════════════════" + @echo " 🔨 Building Application Image" + @echo "════════════════════════════════════════" + DOCKER_BUILDKIT=$(DOCKER_BUILDKIT) docker buildx build \ + -f docker/Dockerfile \ + -t hub.peikarband.ir/peikarband/landing:$(VERSION) \ + -t hub.peikarband.ir/peikarband/landing:latest \ + --build-arg BASE_IMAGE=hub.peikarband.ir/peikarband/landing:base \ --build-arg VERSION=$(VERSION) \ --build-arg BUILD_DATE=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') \ + --platform linux/amd64 \ + --load \ . + @echo "" + @echo "✅ Application image built: hub.peikarband.ir/peikarband/landing:$(VERSION)" + @echo "" docker-push: - docker tag $(IMAGE_NAME):$(VERSION) $(REGISTRY)/$(IMAGE_NAME):$(VERSION) - docker tag $(IMAGE_NAME):$(VERSION) $(REGISTRY)/$(IMAGE_NAME):latest - docker push $(REGISTRY)/$(IMAGE_NAME):$(VERSION) - docker push $(REGISTRY)/$(IMAGE_NAME):latest + @echo "════════════════════════════════════════" + @echo " 📤 Pushing Application Image" + @echo "════════════════════════════════════════" + docker push hub.peikarband.ir/peikarband/landing:$(VERSION) + docker push hub.peikarband.ir/peikarband/landing:latest + @echo "" + @echo "✅ Application image pushed successfully!" + @echo "" docker-login: @echo "Logging in to Harbor registry..." - @docker login $(REGISTRY) + @docker login hub.peikarband.ir docker-up: - docker-compose up -d + docker-compose -f docker/docker-compose.yml up -d docker-down: - docker-compose down + docker-compose -f docker/docker-compose.yml down # Helm commands helm-lint: @@ -135,8 +201,8 @@ k8s-deploy: docker-build docker-push helm-upgrade # Database migrate: - alembic upgrade head + cd peikarband && alembic -c config/alembic.ini upgrade head seed: - python3 scripts/seed_database.py + cd peikarband && python3 tools/scripts/seed_database.py diff --git a/README.md b/README.md index 339e857..3820bff 100644 --- a/README.md +++ b/README.md @@ -1,217 +1,43 @@ -# پیکربند - پلتفرم جامع مدیریت هاستینگ و زیرساخت ابری +# Peikarband Landing Platform -## 📖 درباره پروژه +یک پلتفرم حرفه‌ای برای مدیریت هاستینگ، سرورهای ابری و خدمات DevOps. -پیکربند یک پلتفرم حرفه‌ای برای مدیریت هاستینگ، سرورهای ابری، دامین و خدمات DevOps است. این پلتفرم با الهام از سرویس‌هایی مانند Cloudways، DigitalOcean و پارس پک طراحی شده است. +## ساختار پروژه -## 🏗️ معماری - -این پروژه بر اساس **Clean Architecture** و اصول **SOLID** طراحی شده است: - -- **Domain Layer**: منطق کسب‌وکار اصلی -- **Application Layer**: موارد استفاده (Use Cases) -- **Infrastructure Layer**: پیاده‌سازی‌های فنی -- **Presentation Layer**: رابط کاربری (Reflex) - -## 🚀 تکنولوژی‌ها - -- **Frontend/Backend**: Python Reflex -- **Database**: PostgreSQL + SQLAlchemy -- **Cache**: Redis -- **Task Queue**: Celery -- **Testing**: pytest -- **Code Quality**: black, flake8, mypy, isort - -## 📋 پیش‌نیازها - -- Python 3.11+ -- PostgreSQL 14+ -- Redis 7+ -- Node.js 18+ (برای Reflex) - -## 🛠️ نصب و راه‌اندازی - -### 1. کلون کردن پروژه - -```bash -git clone https://github.com/yourusername/peikarband.git -cd peikarband +``` +landing/ +├── Makefile # Build و deployment commands +├── .gitignore +├── .woodpecker.yml # CI/CD pipeline +│ +├── helm/ # Kubernetes deployment +│ └── peikarband/ +│ +├── docker/ # Docker build configs +│ ├── Dockerfile +│ └── docker-compose.yml +│ +└── peikarband/ # Source code و مستندات + ├── README.md # مستندات کامل + ├── src/ # Application code + ├── tests/ # Tests + └── ... ``` -### 2. ایجاد محیط مجازی +## دستورات سریع ```bash -python -m venv venv -source venv/bin/activate # On Windows: venv\Scripts\activate -``` - -### 3. نصب وابستگی‌ها - -```bash -pip install -r requirements.txt -pip install -r requirements-dev.txt # برای توسعه -``` - -### 4. تنظیم Environment Variables - -```bash -cp .env.example .env -# ویرایش .env و تکمیل مقادیر -``` - -### 5. راه‌اندازی دیتابیس - -```bash -# ایجاد دیتابیس -createdb peikarband - -# اجرای migrations -alembic upgrade head -``` - -### 6. اجرای پروژه - -```bash -# توسعه -python -m reflex run - -# یا +# Development make dev + +# Docker build +make docker-build + +# Helm deploy +make helm-upgrade + +# برای اطلاعات بیشتر +cd peikarband/ +cat README.md ``` -## 🚢 Deployment - -### با Docker - -```bash -# Build -docker build -t peikarband:latest . - -# Run -docker-compose up -d -``` - -### با Kubernetes/Helm - -```bash -# Deploy -helm upgrade --install peikarband ./helm/peikarband \ - --namespace production \ - --set image.tag=0.1.0 - -# یا -make k8s-deploy -``` - -📖 [راهنمای کامل Deployment](docs/deployment/kubernetes.md) - -## 📁 ساختار پروژه - -``` -peikarband/ -├── docs/ # مستندات -├── src/ -│ ├── config/ # تنظیمات -│ ├── core/ # هسته اصلی -│ │ ├── domain/ # Domain entities & logic -│ │ └── application/ # Use cases & DTOs -│ ├── infrastructure/ # پیاده‌سازی‌های فنی -│ ├── presentation/ # رابط کاربری -│ └── shared/ # کدهای مشترک -├── tests/ # تست‌ها -└── scripts/ # اسکریپت‌های کمکی -``` - -## 🧪 تست - -```bash -# اجرای همه تست‌ها -pytest - -# با coverage -pytest --cov=src tests/ - -# تست‌های خاص -pytest tests/unit/ -pytest tests/integration/ -``` - -## 📝 کدنویسی - -### استانداردها - -- **PEP 8**: استاندارد کدنویسی Python -- **PEP 20**: Zen of Python -- **Type Hints**: همه جا استفاده شود -- **Docstrings**: Google Style - -### ابزارهای کیفیت کد - -```bash -# Format -black src/ - -# Linting -flake8 src/ - -# Type checking -mypy src/ - -# Import sorting -isort src/ -``` - -### Pre-commit Hooks - -```bash -pre-commit install -pre-commit run --all-files -``` - -## 📚 مستندات - -مستندات کامل در پوشه `docs/` موجود است: - -- [Handbook](docs/handbook.md): راهنمای جامع پروژه -- [Architecture](docs/architecture/): معماری سیستم -- [Development](docs/development/): راهنمای توسعه -- [API Reference](docs/api/): مستندات API - -## 🔐 امنیت - -- همه پسوردها با bcrypt hash می‌شوند -- استفاده از JWT برای authentication -- پشتیبانی از 2FA -- اطلاعات حساس رمزنگاری می‌شوند - -## 🤝 مشارکت - -برای مشارکت در پروژه: - -1. Fork کنید -2. Branch جدید بسازید (`git checkout -b feature/amazing-feature`) -3. Commit کنید (`git commit -m 'feat: add amazing feature'`) -4. Push کنید (`git push origin feature/amazing-feature`) -5. Pull Request بسازید - -## 📄 لایسنس - -این پروژه تحت لایسنس MIT منتشر شده است. - -## 👥 تیم - -- Lead Developer: [Your Name] -- Architecture: Clean Architecture -- Methodology: Agile/Scrum - -## 📞 تماس - -- Website: https://peikarband.ir -- Email: support@peikarband.ir -- Telegram: @peikarband - ---- - -**نسخه**: 0.1.0 -**آخرین بروزرسانی**: 2025-01-24 - diff --git a/argocd/README.md b/argocd/README.md deleted file mode 100644 index d5a25a2..0000000 --- a/argocd/README.md +++ /dev/null @@ -1,154 +0,0 @@ -# ArgoCD Deployment - -This directory contains ArgoCD Application manifests for deploying Peikarband to Kubernetes. - -## Files - -- `application.yaml`: Production deployment (main branch → peikarband namespace) -- `application-staging.yaml`: Staging deployment (develop branch → peikarband-staging namespace) - -## Prerequisites - -1. ArgoCD installed in your cluster -2. Git repository access configured in ArgoCD -3. Docker registry credentials (if using private registry) - -## Deployment - -### 1. Add Git Repository to ArgoCD - -```bash -# For HTTPS with token -argocd repo add https://git.peikarband.ir/ehsan-minadd/peikarband.git \ - --username YOUR_USERNAME \ - --password YOUR_ACCESS_TOKEN - -# Or using argocd UI: Settings → Repositories → Connect Repo -``` - -### 2. Deploy Production - -```bash -kubectl apply -f argocd/application.yaml -``` - -### 3. Deploy Staging - -```bash -kubectl apply -f argocd/application-staging.yaml -``` - -## Sync Policy - -Both applications use **automatic sync** with: -- **Auto-prune**: Remove resources deleted from Git -- **Self-heal**: Automatically sync when cluster state differs from Git -- **Retry logic**: 5 attempts with exponential backoff - -## Monitoring - -```bash -# Check application status -argocd app get peikarband -argocd app get peikarband-staging - -# Watch sync progress -argocd app sync peikarband --watch - -# View logs -argocd app logs peikarband -``` - -## Manual Sync - -```bash -# Force sync -argocd app sync peikarband --force - -# Sync with prune -argocd app sync peikarband --prune -``` - -## Rollback - -```bash -# List history -argocd app history peikarband - -# Rollback to specific revision -argocd app rollback peikarband -``` - -## Architecture - -``` -┌─────────────────────────────────────────────────┐ -│ ArgoCD │ -│ ┌───────────────────┐ ┌──────────────────┐ │ -│ │ Production App │ │ Staging App │ │ -│ │ (main branch) │ │ (develop branch) │ │ -│ └─────────┬─────────┘ └────────┬─────────┘ │ -└────────────┼─────────────────────┼──────────────┘ - │ │ - ▼ ▼ - ┌────────────────┐ ┌─────────────────┐ - │ namespace: │ │ namespace: │ - │ peikarband │ │ peikarband-stg │ - └────────────────┘ └─────────────────┘ -``` - -## Environment Variables - -Override via Helm values: - -```yaml -# In values-production.yaml or values-staging.yaml -env: - - name: DATABASE_URL - value: "postgresql://..." - - name: REDIS_URL - value: "redis://..." -``` - -## Secrets Management - -Secrets should be managed outside Git: - -```bash -# Using kubectl -kubectl create secret generic peikarband-secrets \ - --from-literal=database-password=xxx \ - --namespace=peikarband - -# Or using Sealed Secrets, External Secrets Operator, etc. -``` - -## Troubleshooting - -### Application Out of Sync - -```bash -argocd app sync peikarband --force -``` - -### Image Pull Errors - -Check registry credentials: -```bash -kubectl get secret regcred -n peikarband -o yaml -``` - -### Health Check Failing - -View pod logs: -```bash -kubectl logs -n peikarband -l app=peikarband --tail=100 -``` - -### Helm Values Override Not Working - -Verify values file path in Application manifest: -```bash -argocd app manifests peikarband | grep valueFiles -``` - diff --git a/banner-3.gif b/banner-3.gif deleted file mode 100644 index 93c2f3f..0000000 Binary files a/banner-3.gif and /dev/null differ diff --git a/build-base-image.sh b/build-base-image.sh new file mode 100755 index 0000000..5933450 --- /dev/null +++ b/build-base-image.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Helper script to build and push base image locally + +set -e + +echo "=== Building Peikarband Base Image ===" +echo "" + +# Variables +REGISTRY="hub.peikarband.ir" +IMAGE="$REGISTRY/peikarband/base" + +# Build +echo "1. Building base image..." +docker build \ + -f docker/Dockerfile.base \ + -t "$IMAGE:latest" \ + -t "$IMAGE:python3.11-node20" \ + --build-arg PYTHON_VERSION=3.11 \ + --build-arg NODE_VERSION=20 \ + . + +echo "" +echo "2. Testing base image..." +docker run --rm "$IMAGE:latest" bash -c "python --version && node --version && bun --version" + +echo "" +echo "3. Login to Harbor registry..." +docker login "$REGISTRY" + +echo "" +echo "4. Pushing base image..." +docker push "$IMAGE:latest" +docker push "$IMAGE:python3.11-node20" + +echo "" +echo "=== ✅ Base Image Built and Pushed Successfully! ===" +echo "" +echo "Base image is now available at:" +echo " - $IMAGE:latest" +echo " - $IMAGE:python3.11-node20" +echo "" +echo "You can now run the application pipeline." diff --git a/build-base-local.sh b/build-base-local.sh new file mode 100755 index 0000000..b622543 --- /dev/null +++ b/build-base-local.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# Build and push base image locally +# Usage: ./build-base-local.sh + +set -e + +echo "════════════════════════════════════════" +echo " 🔨 Building Base Image Locally" +echo "════════════════════════════════════════" +echo "" + +# Configuration +REGISTRY="hub.peikarband.ir" +REPO="peikarband/base" +TAG="latest" +PYTHON_VERSION="3.11" +NODE_VERSION="20" + +# Full image name +IMAGE="${REGISTRY}/${REPO}:${TAG}" + +echo "📦 Image: ${IMAGE}" +echo "🐍 Python: ${PYTHON_VERSION}" +echo "📦 Node.js: ${NODE_VERSION}" +echo "" + +# Check if docker buildx is available +if ! docker buildx version &> /dev/null; then + echo "❌ docker buildx not found!" + echo "Please install Docker Buildx" + exit 1 +fi + +# Login to registry +echo "🔐 Logging in to registry..." +echo "" +read -p "Harbor Username: " HARBOR_USERNAME +read -sp "Harbor Password: " HARBOR_PASSWORD +echo "" +echo "" + +echo "$HARBOR_PASSWORD" | docker login "$REGISTRY" -u "$HARBOR_USERNAME" --password-stdin + +# Create/use buildx builder +echo "" +echo "🏗️ Setting up builder..." +docker buildx create --use --name peikarband-builder 2>/dev/null || docker buildx use peikarband-builder + +# Build and push +echo "" +echo "🔨 Building base image..." +echo "(This will take ~8-10 minutes on first build)" +echo "" + +docker buildx build \ + -f docker/Dockerfile.base \ + -t "${IMAGE}" \ + -t "${REGISTRY}/${REPO}:python${PYTHON_VERSION}-node${NODE_VERSION}" \ + --build-arg PYTHON_VERSION="${PYTHON_VERSION}" \ + --build-arg NODE_VERSION="${NODE_VERSION}" \ + --platform linux/amd64 \ + --push \ + --progress=plain \ + . + +echo "" +echo "════════════════════════════════════════" +echo " ✅ Base Image Built Successfully!" +echo "════════════════════════════════════════" +echo "" +echo "📦 Image: ${IMAGE}" +echo "" +echo "Tags pushed:" +echo " • latest" +echo " • python${PYTHON_VERSION}-node${NODE_VERSION}" +echo "" +echo "Now you can build your app with:" +echo " make docker-build" +echo "" +echo "Or in CI, it will automatically use this base image." +echo "" + diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..786e04a --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,153 @@ +# Dockerfile - Peikarband Landing Application +# Optimized multi-stage build using base image + +# Build arguments +ARG BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest +ARG VERSION=latest +ARG BUILD_DATE + +# ============================================ +# Stage 1: Builder (using base image) +# ============================================ +FROM ${BASE_IMAGE} AS builder + +LABEL stage=builder +LABEL maintainer="Peikarband DevOps " + +WORKDIR /build + +# Base image already has: +# - Python 3.11 +# - Node.js 20 +# - bun +# - gcc, g++, make, curl, ca-certificates + +# Verify tools are available +RUN echo "=== Build Environment ===" && \ + python --version && \ + node --version && \ + npm --version && \ + bun --version && \ + echo "========================" + +# ============================================ +# Python Dependencies +# ============================================ + +# Copy Python requirements first (for layer caching) +COPY peikarband/requirements.txt . + +# Install Python dependencies +RUN --mount=type=cache,target=/root/.cache/pip \ + pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir -r requirements.txt + +# ============================================ +# Frontend Build (Reflex) +# ============================================ + +# Copy source code +COPY peikarband/ . + +# Initialize Reflex and build frontend +RUN reflex init --loglevel debug || true && \ + reflex export --frontend-only --no-zip --loglevel debug || echo "Export completed with warnings" + +# Build frontend with npm (fallback if reflex export fails) +WORKDIR /build/.web + +# Configure npm for better reliability +RUN npm config set fetch-retry-mintimeout 20000 && \ + npm config set fetch-retry-maxtimeout 120000 && \ + npm config set fetch-retries 5 && \ + npm config set fetch-timeout 300000 + +# Install and build +RUN --mount=type=cache,target=/root/.npm \ + npm ci --prefer-offline --no-audit --loglevel verbose && \ + npm run build + +# ============================================ +# Stage 2: Runtime (using base image for Node.js) +# ============================================ +FROM ${BASE_IMAGE} AS runtime + +LABEL org.opencontainers.image.title="Peikarband Landing" +LABEL org.opencontainers.image.description="Peikarband hosting platform landing page" +LABEL org.opencontainers.image.vendor="Peikarband" +LABEL org.opencontainers.image.version="${VERSION}" +LABEL org.opencontainers.image.created="${BUILD_DATE}" + +# Create non-root user +RUN groupadd -r peikarband && \ + useradd -r -g peikarband -u 1000 -m -s /bin/bash peikarband + +WORKDIR /app + +# Base image already has everything we need: +# - Python 3.11 +# - Node.js 20 +# - curl, ca-certificates +# - tini (for proper init) +# No additional packages needed! + +# Copy Python dependencies from builder +COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages +COPY --from=builder /usr/local/bin /usr/local/bin + +# Copy application code +COPY --from=builder --chown=peikarband:peikarband /build /app + +# Create necessary directories +RUN mkdir -p /app/data /app/logs /app/uploaded_files && \ + chown -R peikarband:peikarband /app + +# Set proper permissions +RUN chmod -R 755 /app && \ + chmod -R 777 /app/data /app/logs /app/uploaded_files + +# Environment variables +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PYTHONPATH=/app \ + PATH="/app/.venv/bin:$PATH" \ + REFLEX_DIR=/app \ + NODE_ENV=production + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ + CMD curl -f http://localhost:${PORT:-3000}/_health || exit 1 + +# Switch to non-root user +USER peikarband + +# Expose port +EXPOSE 3000 8000 + +# Use tini as init system +ENTRYPOINT ["/usr/bin/tini", "--"] + +# Start application +CMD ["reflex", "run", "--env", "prod", "--loglevel", "info"] + +# ============================================ +# Build Information +# ============================================ +ARG GIT_COMMIT +ARG GIT_BRANCH +ARG BUILD_NUMBER + +LABEL git.commit="${GIT_COMMIT}" +LABEL git.branch="${GIT_BRANCH}" +LABEL build.number="${BUILD_NUMBER}" +LABEL build.date="${BUILD_DATE}" + +# ============================================ +# Multi-Architecture Support +# ============================================ +# This Dockerfile supports: +# - linux/amd64 +# - linux/arm64 (with appropriate base image) +# +# Build with: +# docker buildx build --platform linux/amd64,linux/arm64 . diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base new file mode 100644 index 0000000..8fadc22 --- /dev/null +++ b/docker/Dockerfile.base @@ -0,0 +1,71 @@ +# Peikarband Base Image +# Pre-built image with Python, Node.js, bun, and build tools +# +# Usage: +# Build: docker build -f docker/Dockerfile.base -t hub.peikarband.ir/peikarband/base:latest . +# Or use Woodpecker: trigger .woodpecker-base.yml pipeline +# +# This image is built once and reused by all Peikarband projects + +ARG PYTHON_VERSION=3.11 +ARG NODE_VERSION=20 + +FROM python:${PYTHON_VERSION}-slim + +LABEL maintainer="Peikarband Team " +LABEL org.opencontainers.image.title="Peikarband Base" +LABEL org.opencontainers.image.description="Base image with Python, Node.js, bun, and build tools" + +WORKDIR /build + +# Install system dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc \ + g++ \ + make \ + curl \ + gnupg \ + ca-certificates \ + unzip \ + git \ + tini \ + && rm -rf /var/lib/apt/lists/* + +# Install Node.js +ARG NODE_VERSION +RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - \ + && apt-get install -y --no-install-recommends nodejs \ + && rm -rf /var/lib/apt/lists/* \ + && npm config set fetch-retry-mintimeout 20000 \ + && npm config set fetch-retry-maxtimeout 120000 \ + && npm config set fetch-retries 5 \ + && npm config set fetch-timeout 300000 \ + && npm config set registry https://registry.npmjs.org/ + +# Install bun (required by Reflex for frontend build) +# Retry mechanism for network issues +RUN set -ex && \ + for i in 1 2 3 4 5; do \ + curl -fsSL https://bun.sh/install | bash && break || \ + (echo "Attempt $i failed, retrying in 5 seconds..." && sleep 5); \ + done || (echo "Failed to install bun after 5 attempts" && exit 1) + +# Add bun to PATH +ENV PATH="/root/.bun/bin:${PATH}" + +# Upgrade pip, setuptools, wheel +RUN pip install --no-cache-dir --upgrade pip setuptools wheel + +# Verify installations +RUN python --version && \ + node --version && \ + npm --version && \ + bun --version && \ + pip --version + +# Set working directory +WORKDIR /build + +# Default command +CMD ["/bin/bash"] + diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..03941e8 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,81 @@ +# Build Directory + +این دایرکتوری شامل همه فایل‌های مربوط به **build process** پروژه است. + +## 📁 ساختار + +``` +build/ +├── docker/ # Docker configurations +│ ├── Dockerfile # Main application Dockerfile +│ ├── Dockerfile.base # Base image reference +│ ├── docker-compose.yml # Local development +│ └── .dockerignore +└── ci/ # CI/CD configurations + └── woodpecker.yml # Woodpecker CI pipeline +``` + +## 🐳 Docker + +### Dockerfile +Multi-stage Dockerfile برای بهینه‌سازی حجم image و امنیت: +- **Stage 1 (Builder)**: Build و compile +- **Stage 2 (Runtime)**: Image نهایی بدون build tools + +**Build:** +```bash +make docker-build +# یا +docker build -f build/docker/Dockerfile -t peikarband/landing:latest . +``` + +### Dockerfile.base +فایل مرجع برای base image که در repo جداگانه build می‌شود: +- Repo: `peikarband/base` +- Registry: `hub.peikarband.ir/peikarband/base:latest` + +### docker-compose.yml +برای development محلی: +```bash +make docker-up +# یا +docker-compose -f build/docker/docker-compose.yml up -d +``` + +## 🔄 CI/CD + +### woodpecker.yml +Woodpecker CI pipeline configuration: +- Build Docker image +- Push به Harbor registry +- Tag with commit SHA +- Cache optimization + +**تنظیمات مورد نیاز:** +- `HARBOR_USERNAME`: Harbor registry username +- `HARBOR_PASSWORD`: Harbor registry password + +## 🎯 Best Practices + +1. **Docker Images** + - Multi-stage builds + - Minimal runtime dependencies + - Non-root user + - Health checks + +2. **CI/CD** + - Cache layers + - Automated testing + - Semantic versioning + - Registry push on main branch only + +3. **Security** + - Scan images for vulnerabilities + - Sign images + - Use specific versions (no `:latest` in production) + +## 📚 مستندات بیشتر + +- [Deployment Guide](../docs/deployment/kubernetes.md) +- [Production Deployment](../docs/deployment/PRODUCTION_DEPLOYMENT.md) + diff --git a/docker-compose.yml b/docker/docker-compose.yml similarity index 91% rename from docker-compose.yml rename to docker/docker-compose.yml index f424bf5..d9e07e6 100644 --- a/docker-compose.yml +++ b/docker/docker-compose.yml @@ -35,7 +35,9 @@ services: # Peikarband Application app: - build: . + build: + context: .. + dockerfile: docker/Dockerfile container_name: peikarband-app depends_on: - postgres @@ -57,7 +59,9 @@ services: # Celery Worker celery: - build: . + build: + context: .. + dockerfile: docker/Dockerfile container_name: peikarband-celery command: celery -A src.infrastructure.tasks.celery_app worker -l info depends_on: @@ -74,7 +78,9 @@ services: # Flower (Celery Monitoring) flower: - build: . + build: + context: .. + dockerfile: docker/Dockerfile container_name: peikarband-flower command: celery -A src.infrastructure.tasks.celery_app flower depends_on: diff --git a/docs/BASE_IMAGE.md b/docs/BASE_IMAGE.md new file mode 100644 index 0000000..c7eec29 --- /dev/null +++ b/docs/BASE_IMAGE.md @@ -0,0 +1,198 @@ +# Base Image Management + +## چرا Base Image؟ + +Base image شامل تمام dependencies سنگین است که: +- ✅ فقط یک بار build می‌شود +- ✅ هر بار که کد تغییر می‌کند، دوباره download نمی‌شود +- ✅ Build time را از 8-10 دقیقه به 3-4 دقیقه کاهش می‌دهد +- ✅ قابل استفاده مجدد در چند پروژه + +## محتویات Base Image + +Base image شامل موارد زیر است: + +```dockerfile +FROM python:3.11-slim + +# Build Tools +- gcc, g++, make +- curl, ca-certificates +- git, unzip + +# Runtime +- Python 3.11 +- Node.js 20.x +- npm (latest) +- bun (latest) +``` + +## ساخت Base Image + +### روش 1: Local (توصیه می‌شود برای اولین بار) + +```bash +# Run the helper script +./build-base-local.sh +``` + +این script: +1. از شما username/password Harbor می‌خواهد +2. به registry login می‌کند +3. Base image را build می‌کند +4. به Harbor push می‌کند + +**زمان:** ~8-10 دقیقه (اولین بار) + +### روش 2: در Woodpecker CI + +```bash +# Trigger pipeline manually in Woodpecker UI +# یا از طریق git: +git commit --allow-empty -m "build: rebuild base image" +git push +``` + +Base image فقط در این حالت‌ها rebuild می‌شود: +- `docker/Dockerfile.base` تغییر کرد +- `.woodpecker.yml` تغییر کرد +- Manual trigger + +## استفاده از Base Image + +Dockerfile به صورت خودکار از base image استفاده می‌کند: + +```dockerfile +ARG BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest +FROM ${BASE_IMAGE} AS builder +``` + +## مدیریت Versions + +### Tags: + +1. **`latest`**: آخرین نسخه (default) +2. **`python3.11-node20`**: نسخه specific + +### تغییر Version: + +اگر می‌خواهید Python یا Node.js version تغییر کند: + +1. Edit `docker/Dockerfile.base`: + ```dockerfile + ARG PYTHON_VERSION=3.12 # تغییر + ARG NODE_VERSION=22 # تغییر + ``` + +2. Build base image: + ```bash + ./build-base-local.sh + ``` + +3. Update app Dockerfile: + ```dockerfile + ARG BASE_IMAGE=hub.peikarband.ir/peikarband/base:python3.12-node22 + ``` + +## Troubleshooting + +### مشکل: Base image not found + +```bash +# Build locally: +./build-base-local.sh + +# یا check if exists: +docker pull hub.peikarband.ir/peikarband/base:latest +``` + +### مشکل: Build fails in CI + +```bash +# Check Woodpecker secrets: +- HARBOR_USERNAME +- HARBOR_PASSWORD + +# Test locally: +docker login hub.peikarband.ir +``` + +### مشکل: Base image outdated + +```bash +# Force rebuild: +git commit --allow-empty -m "build: rebuild base image" +git push + +# یا locally: +./build-base-local.sh +``` + +## Build Times + +| Scenario | With Base | Without Base | +|----------|-----------|--------------| +| First build | 10 min | 10 min | +| Code change only | 3 min ✅ | 10 min ❌ | +| Dependency change | 3 min ✅ | 10 min ❌ | +| Base change | 13 min | 10 min | + +## Best Practices + +1. **Build base image locally اولین بار** + ```bash + ./build-base-local.sh + ``` + +2. **فقط وقتی dependencies تغییر کرد rebuild کنید** + - Python packages + - Node.js version + - System tools + +3. **از versioned tags استفاده کنید در production** + ```dockerfile + ARG BASE_IMAGE=hub.peikarband.ir/peikarband/base:python3.11-node20 + ``` + +4. **Base image را در Harbor نگه دارید** + - Private registry + - Version control + - Team access + +## مثال: Workflow کامل + +```bash +# 1. Clone project +git clone +cd peikarband + +# 2. Build base image (فقط یک بار) +./build-base-local.sh +# ⏱️ ~8-10 دقیقه + +# 3. Build app (بعدها) +make docker-build +# ⏱️ ~3 دقیقه ✅ + +# 4. تغییر کد +vim peikarband/src/... + +# 5. Build again (سریع!) +make docker-build +# ⏱️ ~3 دقیقه ✅ (dependencies از cache) +``` + +## خلاصه + +✅ **مزایا:** +- Build سریع‌تر (3 دقیقه vs 10 دقیقه) +- بهینه‌سازی cache +- قابل استفاده مجدد + +❌ **نیاز به:** +- Build اولیه (یک بار، 10 دقیقه) +- نگهداری در registry +- Rebuild وقتی dependencies تغییر کند + +**نتیجه:** برای development و production **بسیار** مفید است! 🚀 + diff --git a/docs/BASE_IMAGE_MANAGEMENT.md b/docs/BASE_IMAGE_MANAGEMENT.md new file mode 100644 index 0000000..9c676d6 --- /dev/null +++ b/docs/BASE_IMAGE_MANAGEMENT.md @@ -0,0 +1,409 @@ +# مدیریت Base Image + +این مستند راهنمای کامل برای مدیریت و استفاده از base image در پروژه Peikarband است. + +## نمای کلی + +**Base Image چیست؟** + +Base image یک Docker image از پیش ساخته شده است که شامل تمام ابزارهای مورد نیاز برای build اپلیکیشن است: +- Python 3.11 +- Node.js 20 +- Bun (برای Reflex frontend) +- Build tools (gcc, g++, make) +- Git و curl + +**چرا Base Image؟** + +✅ **سرعت Build:** 8-10 دقیقه → 2-3 دقیقه +✅ **قابلیت اطمینان:** بدون نیاز به دانلود مکرر npm/bun +✅ **Consistency:** همه builds از همان environment استفاده می‌کنند +✅ **Network Resilience:** مشکلات network کمتر + +## ساختار فایل‌ها + +``` +. +├── docker/ +│ ├── Dockerfile # استفاده از base image +│ └── Dockerfile.base # تعریف base image +├── .woodpecker.yml # Build اپلیکیشن (از base استفاده می‌کند) +└── .woodpecker-base.yml # Build base image (manual/on-change) +``` + +## Base Image Tags + +``` +hub.peikarband.ir/peikarband/base:latest # آخرین version +hub.peikarband.ir/peikarband/base:python3.11-node20 # Version specific +hub.peikarband.ir/peikarband/base:python3.11-node20-a1b2c3d4 # With commit SHA +``` + +## چگونه Base Image را Build کنیم؟ + +### روش 1: Manual Trigger در Woodpecker (پیشنهادی) + +1. رفتن به Woodpecker UI +2. انتخاب repository: `peikarband/landing` +3. کلیک روی "Pipelines" +4. کلیک روی "New Pipeline" +5. انتخاب pipeline: `.woodpecker-base.yml` +6. کلیک روی "Start" + +### روش 2: Push تغییرات Dockerfile.base + +هر بار که `docker/Dockerfile.base` تغییر کند، pipeline به‌طور خودکار trigger می‌شود: + +```bash +# تغییر Dockerfile.base +vim docker/Dockerfile.base + +# Commit و push +git add docker/Dockerfile.base +git commit -m "chore: update base image to Node.js 21" +git push origin main + +# Pipeline به‌طور خودکار اجرا می‌شود +``` + +### روش 3: Local Build (برای تست) + +```bash +# Build locally +docker build -f docker/Dockerfile.base \ + -t hub.peikarband.ir/peikarband/base:latest \ + --build-arg PYTHON_VERSION=3.11 \ + --build-arg NODE_VERSION=20 \ + . + +# Test locally +docker run --rm hub.peikarband.ir/peikarband/base:latest \ + bash -c "python --version && node --version && bun --version" + +# Push to registry +docker login hub.peikarband.ir +docker push hub.peikarband.ir/peikarband/base:latest +docker push hub.peikarband.ir/peikarband/base:python3.11-node20 +``` + +## چگونه Application از Base Image استفاده می‌کند؟ + +Pipeline اصلی (`.woodpecker.yml`) به‌طور خودکار از base image استفاده می‌کند: + +### مرحله 1: Check Base Image + +```yaml +check-base-image: + # بررسی می‌کند که base image در registry موجود است + # اگر نباشد، error می‌دهد و راهنمایی می‌کند +``` + +### مرحله 2: Build Application + +```yaml +build-image: + build_args: + - BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest + push: false # فقط build، بدون push +``` + +### مرحله 3: Push Application + +```yaml +push-image: + tags: + - latest + - ${CI_COMMIT_SHA:0:8} + - ${CI_COMMIT_BRANCH} + push: true # حالا push می‌کنیم +``` + +### مرحله 4: Verify + +```yaml +verify-push: + # تایید می‌کند که image با موفقیت push شده +``` + +## چه زمانی باید Base Image را Rebuild کنیم؟ + +### Rebuild ضروری است: + +1. **تغییر Python version:** + ```bash + # در Dockerfile.base + ARG PYTHON_VERSION=3.12 # تغییر از 3.11 + ``` + +2. **تغییر Node.js version:** + ```bash + # در Dockerfile.base + ARG NODE_VERSION=21 # تغییر از 20 + ``` + +3. **اضافه کردن system dependencies:** + ```dockerfile + RUN apt-get install -y \ + gcc g++ make \ + postgresql-dev # جدید + ``` + +4. **تغییر bun installation:** + ```dockerfile + # اگر روش نصب bun تغییر کند + ``` + +### Rebuild اختیاری است: + +1. **تغییرات جزئی در Dockerfile اصلی** +2. **تغییر کد اپلیکیشن** +3. **تغییر Helm charts** + +## مدیریت Versions + +### Strategy ما: + +``` +latest → همیشه آخرین version +python3.11-node20 → Version مشخص (stable) +python3.11-node20-a1b2c3d4 → با commit SHA (rollback) +``` + +### مثال: Update به Python 3.12 + +```bash +# 1. تغییر Dockerfile.base +vim docker/Dockerfile.base +# ARG PYTHON_VERSION=3.12 + +# 2. Commit +git add docker/Dockerfile.base +git commit -m "chore: upgrade base image to Python 3.12" +git push origin main + +# 3. Wait for .woodpecker-base.yml to complete + +# 4. تغییر تگ در application Dockerfile (اختیاری) +vim docker/Dockerfile +# ARG BASE_IMAGE=hub.peikarband.ir/peikarband/base:python3.12-node20 + +# 5. Test application build +git add docker/Dockerfile +git commit -m "chore: use Python 3.12 base image" +git push origin main +``` + +## Troubleshooting + +### خطا: "Base image not found" + +**علت:** Base image هنوز build نشده یا در registry موجود نیست + +**راه‌حل:** + +```bash +# 1. بررسی کنید که base image در registry موجود است +curl -u "admin:password" \ + https://hub.peikarband.ir/v2/peikarband/base/tags/list + +# 2. اگر موجود نیست، pipeline base را اجرا کنید +# Manual trigger در Woodpecker UI → .woodpecker-base.yml + +# 3. یا local build: +docker build -f docker/Dockerfile.base -t hub.peikarband.ir/peikarband/base:latest . +docker push hub.peikarband.ir/peikarband/base:latest +``` + +### خطا: "Failed to pull base image" + +**علت:** Registry authentication مشکل دارد + +**راه‌حل:** + +```bash +# 1. بررسی credentials در Woodpecker secrets +# Repository → Settings → Secrets → HARBOR_USERNAME, HARBOR_PASSWORD + +# 2. Test login locally +docker login hub.peikarband.ir +Username: admin +Password: [your-password] + +# 3. Test pull +docker pull hub.peikarband.ir/peikarband/base:latest +``` + +### Base Image خیلی بزرگ است + +**بررسی اندازه:** + +```bash +# Check image size +docker images hub.peikarband.ir/peikarband/base +``` + +**Optimization:** + +```dockerfile +# در Dockerfile.base + +# 1. حذف apt cache +RUN apt-get update && apt-get install -y ... \ + && rm -rf /var/lib/apt/lists/* # این خط مهم است + +# 2. حذف npm cache +RUN npm cache clean --force + +# 3. استفاده از slim image +FROM python:3.11-slim # نه python:3.11 +``` + +### Build Time هنوز کند است + +**بررسی:** + +```bash +# 1. آیا واقعاً از base image استفاده می‌شود؟ +docker history hub.peikarband.ir/peikarband/landing:latest | grep base + +# 2. آیا cache درست کار می‌کند؟ +# در .woodpecker.yml: +cache_from: type=registry,ref=... +``` + +**بهبود:** + +```yaml +# در .woodpecker.yml +build-image: + settings: + # Pull base image first for caching + pull: true + cache_from: + - type=registry,ref=hub.peikarband.ir/peikarband/base:latest + - type=registry,ref=hub.peikarband.ir/peikarband/landing:buildcache +``` + +## Best Practices + +### 1. Version Pinning + +❌ **بد:** +```dockerfile +FROM hub.peikarband.ir/peikarband/base:latest +``` + +✅ **خوب (برای production):** +```dockerfile +FROM hub.peikarband.ir/peikarband/base:python3.11-node20 +``` + +### 2. Testing Base Changes + +قبل از اینکه base image جدید را در production استفاده کنید: + +```bash +# 1. Build base با tag test +docker build -f docker/Dockerfile.base \ + -t hub.peikarband.ir/peikarband/base:test . + +# 2. Test application با این base +docker build --build-arg BASE_IMAGE=hub.peikarband.ir/peikarband/base:test \ + -f docker/Dockerfile . + +# 3. اگر موفق بود، tag را به latest تغییر دهید +docker tag hub.peikarband.ir/peikarband/base:test \ + hub.peikarband.ir/peikarband/base:latest +docker push hub.peikarband.ir/peikarband/base:latest +``` + +### 3. Documentation + +هر بار که base image را تغییر می‌دهید، در CHANGELOG.md یادداشت کنید: + +```markdown +## [Base Image] 2024-12-30 + +### Changed +- Upgraded Python from 3.11 to 3.12 +- Updated Node.js from 20 to 21 +- Added postgresql-dev for database support + +### Impact +- All future builds will use new base +- Rebuild takes ~10 minutes +- Application builds will be ~30% faster +``` + +### 4. Cleanup Old Images + +```bash +# List all base images +curl -u "admin:password" \ + https://hub.peikarband.ir/v2/peikarband/base/tags/list | jq + +# حذف تگ‌های قدیمی (از Harbor UI) +# Repository → peikarband/base → Tags → Select → Delete +``` + +## Monitoring + +### چگونه بفهمیم base image استفاده می‌شود؟ + +```bash +# 1. از Docker history +docker history hub.peikarband.ir/peikarband/landing:latest + +# 2. از image labels +docker inspect hub.peikarband.ir/peikarband/landing:latest | \ + jq '.[0].Config.Labels' + +# 3. از build logs در Woodpecker +# Stage "check-base-image" باید "✓ Base image found" نمایش دهد +``` + +### Metrics مفید: + +```bash +# Build time comparison +# Before base image: 8-10 min +# After base image: 2-3 min +# Improvement: 60-70% + +# Network usage +# Before: ~500 MB download per build (npm, bun, etc.) +# After: ~50 MB (only base image pull if not cached) +# Improvement: 90% +``` + +## FAQ + +**Q: چند وقت یکبار باید base را rebuild کنیم؟** +A: فقط وقتی که dependencies (Python, Node.js, bun) تغییر می‌کنند. معمولاً هر 2-3 ماه یکبار. + +**Q: آیا می‌توانیم چند base image داشته باشیم؟** +A: بله! مثلاً: +- `base:python3.11-node20` → برای پروژه‌های قدیمی +- `base:python3.12-node21` → برای پروژه‌های جدید + +**Q: اگر base image corrupt شود چه کنیم؟** +A: Application Dockerfile می‌تواند به `python:3.11-slim` fallback کند: +```dockerfile +ARG BASE_IMAGE=hub.peikarband.ir/peikarband/base:latest +FROM ${BASE_IMAGE:-python:3.11-slim} AS builder +``` + +**Q: چگونه base را به پروژه‌های دیگر منتقل کنیم؟** +A: Base image در registry مرکزی است، تمام پروژه‌ها می‌توانند از آن استفاده کنند: +```dockerfile +# در هر پروژه دیگر +FROM hub.peikarband.ir/peikarband/base:latest +``` + +## مراجع + +- [Multi-stage Docker Builds](https://docs.docker.com/build/building/multi-stage/) +- [Docker Build Cache](https://docs.docker.com/build/cache/) +- [Harbor Registry Management](https://goharbor.io/docs/latest/) +- [Woodpecker CI Documentation](https://woodpecker-ci.org/docs/) + diff --git a/docs/REPOSITORY_STRATEGY.md b/docs/REPOSITORY_STRATEGY.md new file mode 100644 index 0000000..9b1b067 --- /dev/null +++ b/docs/REPOSITORY_STRATEGY.md @@ -0,0 +1,94 @@ +# Repository Strategy + +## استراتژی فعلی: Single Repository ✅ + +همه چیز در یک repository: `peikarband/landing` + +### مزایا: +- ساده و قابل مدیریت +- همه چیز در یک جا +- مناسب برای یک پروژه + +### ساختار: +``` +peikarband/landing/ +├── .woodpecker.yml # Application pipeline +├── .woodpecker-base.yml # Base image pipeline +├── docker/ +│ ├── Dockerfile # Application +│ └── Dockerfile.base # Base image +└── ... +``` + +--- + +## استراتژی آینده: Multi Repository (اختیاری) + +اگر پروژه‌های بیشتری اضافه شد، می‌توانید base را جدا کنید. + +### مراحل جداسازی: + +#### 1. ایجاد Repository جدید + +```bash +# Create new repo +mkdir peikarband-base-images +cd peikarband-base-images +git init + +# Structure +mkdir -p python311-node20 +``` + +#### 2. انتقال Base Files + +```bash +# Copy base files +cp ../landing/docker/Dockerfile.base python311-node20/Dockerfile +cp ../landing/.woodpecker-base.yml .woodpecker.yml +``` + +#### 3. Update Application Repository + +در `peikarband/landing`: + +```dockerfile +# docker/Dockerfile +ARG BASE_IMAGE=hub.peikarband.ir/peikarband/base:python311-node20 +FROM ${BASE_IMAGE} AS builder +``` + +#### 4. Registry Organization + +``` +Registry Structure: +hub.peikarband.ir/ +├── peikarband/base # Base images repo +│ ├── python311-node20:latest +│ └── python312-node21:latest +└── peikarband/landing # Application + └── latest +``` + +--- + +## زمان جداسازی + +**جدا کنید وقتی:** +- ✅ 3+ پروژه از همان base استفاده می‌کنند +- ✅ تیم 5+ نفری دارید +- ✅ Base versioning پیچیده شد +- ✅ نیاز به CI/CD مستقل برای base دارید + +**جدا نکنید وقتی:** +- ❌ فقط یک پروژه دارید (فعلی) +- ❌ تیم کوچک است (1-3 نفر) +- ❌ Base خیلی تغییر نمی‌کند + +--- + +## توصیه + +**الان:** یک repository کافیه! 👍 + +**آینده:** اگر پروژه دوم شروع شد، مجدداً ارزیابی کنید. diff --git a/docs/WOODPECKER_CI_CD.md b/docs/WOODPECKER_CI_CD.md new file mode 100644 index 0000000..92760a3 --- /dev/null +++ b/docs/WOODPECKER_CI_CD.md @@ -0,0 +1,586 @@ +# Woodpecker CI/CD Documentation + +این مستند راهنمای کامل برای راه‌اندازی و استفاده از Woodpecker CI/CD pipeline برای پروژه Peikarband است. + +## نمای کلی Pipeline + +Pipeline ما شامل 8 مرحله اصلی است: + +``` +1. Code Quality & Linting + ├── flake8 (Python linting) + ├── black (Code formatting check) + ├── isort (Import sorting) + └── mypy (Type checking) + +2. Security Scanning + ├── bandit (Security vulnerability scan) + └── safety (Dependency vulnerability check) + +3. Testing + └── pytest (Unit & Integration tests with coverage) + +4. Helm Validation + ├── helm lint + └── helm template + +5. Docker Build & Push + └── Multi-platform build with caching + +6. Deploy to Staging + └── Auto-deploy on main/develop branches + +7. Deploy to Production + └── Manual trigger on version tags (v*) + +8. Notifications + └── Success/Failure notifications +``` + +## تنظیمات Secrets + +برای اجرای کامل pipeline، باید secrets زیر را در Woodpecker تنظیم کنید: + +### 1. Registry Secrets (الزامی برای Build) + +```bash +HARBOR_USERNAME=admin +HARBOR_PASSWORD=your_harbor_password +``` + +**نحوه تنظیم در Woodpecker UI:** +1. رفتن به Repository Settings +2. کلیک روی "Secrets" +3. اضافه کردن secret جدید: + - Name: `HARBOR_USERNAME` + - Value: `admin` + - Events: `push, tag` +4. تکرار برای `HARBOR_PASSWORD` + +### 2. Kubernetes Secrets (الزامی برای Deployment) + +#### Staging Environment + +```bash +# Generate base64 encoded kubeconfig +cat ~/.kube/config-staging | base64 -w 0 > kubeconfig-staging-base64.txt + +# Add to Woodpecker as secret +KUBECONFIG_STAGING= +``` + +#### Production Environment + +```bash +# Generate base64 encoded kubeconfig +cat ~/.kube/config-production | base64 -w 0 > kubeconfig-production-base64.txt + +# Add to Woodpecker as secret +KUBECONFIG_PRODUCTION= +``` + +**⚠️ نکات امنیتی:** +- هرگز kubeconfig را در Git commit نکنید +- از RBAC برای محدود کردن دسترسی kubeconfig استفاده کنید +- به‌طور منظم kubeconfig را rotate کنید +- فقط namespace های staging و production دسترسی داشته باشند + +### 3. Optional: ArgoCD Integration + +اگر می‌خواهید از ArgoCD برای deployment استفاده کنید: + +```bash +ARGOCD_SERVER=argocd.peikarband.ir +ARGOCD_AUTH_TOKEN=your_argocd_token +``` + +## Branch Strategy + +Pipeline بر اساس branch و event متفاوت رفتار می‌کند: + +### Pull Request (PR) + +```yaml +Stages: Lint + Test + Security + Helm Lint +Skip: Build, Deploy +Purpose: Code quality validation +``` + +**مثال:** + +```bash +# Create PR +git checkout -b feature/new-feature +git push origin feature/new-feature +# Open PR in GitLab/GitHub -> Pipeline runs automatically +``` + +### Main Branch (Push) + +```yaml +Stages: All stages +Deploy: Staging (automatic) +Tags: latest, main-, +``` + +**مثال:** + +```bash +git checkout main +git pull origin main +git merge feature/new-feature +git push origin main +# -> Automatic: Test -> Build -> Deploy to Staging +``` + +### Develop Branch (Push) + +```yaml +Stages: All stages +Deploy: Staging (automatic) +Tags: develop, develop-, +``` + +**مثال:** + +```bash +git checkout develop +git push origin develop +# -> Automatic: Test -> Build -> Deploy to Staging +``` + +### Version Tags (Production) + +```yaml +Stages: All stages +Deploy: Production (automatic) +Tags: latest, v1.2.3, +``` + +**مثال:** + +```bash +# Create and push version tag +git checkout main +git tag -a v1.0.0 -m "Release v1.0.0" +git push origin v1.0.0 +# -> Automatic: Test -> Build -> Deploy to Production +``` + +## Pipeline Triggers + +### Automatic Triggers + +1. **Push به branch:** + ```bash + git push origin main # Trigger full pipeline + deploy staging + git push origin develop # Trigger full pipeline + deploy staging + git push origin feature/* # No trigger (manual only) + ``` + +2. **Tag push:** + ```bash + git push origin v1.0.0 # Trigger full pipeline + deploy production + ``` + +3. **Pull Request:** + ```bash + # Any PR -> Triggers lint/test/security only + ``` + +### Manual Triggers + +در Woodpecker UI: +1. رفتن به Repository +2. کلیک روی "Pipelines" +3. کلیک روی "New Pipeline" +4. انتخاب branch/commit +5. کلیک روی "Start" + +## Docker Image Tagging + +Pipeline به‌طور خودکار images را با تگ‌های مختلف می‌سازد: + +### Main Branch + +``` +hub.peikarband.ir/peikarband/landing:latest +hub.peikarband.ir/peikarband/landing:main +hub.peikarband.ir/peikarband/landing:a1b2c3d4 # commit SHA +``` + +### Develop Branch + +``` +hub.peikarband.ir/peikarband/landing:develop +hub.peikarband.ir/peikarband/landing:develop-a1b2c3d4 +hub.peikarband.ir/peikarband/landing:a1b2c3d4 +``` + +### Version Tags + +``` +hub.peikarband.ir/peikarband/landing:latest +hub.peikarband.ir/peikarband/landing:v1.0.0 +hub.peikarband.ir/peikarband/landing:a1b2c3d4 +``` + +## Deployment Process + +### Staging Deployment + +**Trigger:** هر push به `main` یا `develop` + +**فرایند:** +1. Tests pass +2. Build Docker image +3. Push to registry with tag `-` +4. Helm upgrade to `staging` namespace +5. Wait for rollout (timeout: 5 minutes) +6. Show pod status + +**Rollback:** + +```bash +# List helm releases +helm list -n staging + +# Rollback to previous version +helm rollback peikarband-staging -n staging + +# Or rollback to specific revision +helm rollback peikarband-staging 5 -n staging +``` + +### Production Deployment + +**Trigger:** Push tag با pattern `v*` (مثل `v1.0.0`) + +**فرایند:** +1. Tests pass +2. Build Docker image +3. Push to registry with tags `latest`, `v1.0.0`, `` +4. Helm upgrade to `production` namespace with production values +5. Wait for rollout (timeout: 10 minutes) +6. Verify deployment +7. Show pod status + +**Rollback:** + +```bash +# Check current status +kubectl get pods -n production + +# Rollback via Helm +helm rollback peikarband -n production + +# Or rollback via kubectl +kubectl rollout undo deployment/peikarband -n production + +# Check rollout status +kubectl rollout status deployment/peikarband -n production +``` + +## Monitoring Pipeline + +### Via Woodpecker UI + +1. رفتن به: `https://woodpecker.peikarband.ir` (یا آدرس Woodpecker شما) +2. انتخاب repository +3. مشاهده لیست pipeline runs +4. کلیک روی یک run برای مشاهده جزئیات + +### Via CLI + +```bash +# Install Woodpecker CLI +curl -L https://github.com/woodpecker-ci/woodpecker/releases/latest/download/woodpecker-cli_linux_amd64.tar.gz | tar xz +sudo mv woodpecker-cli /usr/local/bin/ + +# Configure +export WOODPECKER_SERVER=https://woodpecker.peikarband.ir +export WOODPECKER_TOKEN=your_token + +# List pipelines +woodpecker pipeline ls + +# Show pipeline info +woodpecker pipeline info + +# Show logs +woodpecker pipeline logs + +# Approve waiting pipeline +woodpecker pipeline approve +``` + +## Troubleshooting + +### Pipeline Fails at Lint Stage + +**مشکل:** کد formatting یا linting مشکل دارد + +**راه‌حل:** + +```bash +cd peikarband + +# Fix formatting +black src/ +isort src/ + +# Check linting +flake8 src/ + +# Commit fixes +git add . +git commit -m "fix: code formatting and linting" +git push +``` + +### Pipeline Fails at Test Stage + +**مشکل:** تست‌ها fail می‌شوند + +**راه‌حل:** + +```bash +cd peikarband + +# Run tests locally +pytest tests/ -v + +# Run with coverage +pytest tests/ -v --cov=src + +# Fix tests and re-run +git add . +git commit -m "fix: failing tests" +git push +``` + +### Pipeline Fails at Docker Build + +**مشکل:** Docker build error + +**راه‌حل:** + +```bash +# Test build locally +docker build -f docker/Dockerfile -t test:latest . + +# Check Dockerfile syntax +docker build --check -f docker/Dockerfile . + +# Check build context +ls -la peikarband/ + +# Common issues: +# 1. Missing files in context +# 2. COPY path wrong +# 3. Build args missing +``` + +### Pipeline Fails at Deployment + +**مشکل:** Helm deployment fail + +**راه‌حل:** + +```bash +# Test Helm locally +helm lint helm/peikarband +helm template peikarband helm/peikarband -f helm/peikarband/values-staging.yaml + +# Check kubectl access +kubectl get pods -n staging + +# Check secrets +kubectl get secrets -n staging + +# Check image pull +kubectl describe pod -n staging +``` + +### Secret Not Found Error + +**مشکل:** `Secret not found: HARBOR_USERNAME` + +**راه‌حل:** +1. رفتن به Woodpecker UI > Repository > Settings > Secrets +2. بررسی که secret با نام درست اضافه شده +3. بررسی که secret برای event درست (push, tag, etc.) فعال است +4. بررسی که secret برای branch درست در دسترس است + +### Kubeconfig Invalid + +**مشکل:** `Unable to connect to the server` + +**راه‌حل:** + +```bash +# Test kubeconfig locally +export KUBECONFIG=/path/to/your/kubeconfig +kubectl get pods + +# Re-encode kubeconfig +cat ~/.kube/config | base64 -w 0 + +# Update secret in Woodpecker +# Copy new base64 string to KUBECONFIG_STAGING or KUBECONFIG_PRODUCTION +``` + +## Performance Optimization + +### Build Cache + +Pipeline از Docker layer caching استفاده می‌کند: + +```yaml +cache_from: type=registry,ref=hub.peikarband.ir/peikarband/landing:buildcache +cache_to: type=inline +``` + +**بهینه‌سازی بیشتر:** + +1. **Dependencies Caching:** requirements.txt را قبل از کد اصلی COPY کنید +2. **Multi-stage Build:** از multi-stage builds استفاده کنید +3. **Parallel Stages:** مراحل مستقل را parallel اجرا کنید + +### Pipeline Duration + +زمان تقریبی هر stage: + +``` +Lint stages: ~1-2 minutes +Security scan: ~2-3 minutes +Tests: ~3-5 minutes +Helm validation: ~30 seconds +Docker build: ~5-10 minutes (first time), ~2-3 minutes (cached) +Deployment: ~2-5 minutes +Total: ~15-30 minutes (full pipeline) +``` + +## Best Practices + +### 1. Commit Messages + +از conventional commits استفاده کنید: + +```bash +feat: add new feature +fix: bug fix +docs: documentation changes +style: formatting changes +refactor: code refactoring +test: test changes +chore: build/CI changes +``` + +### 2. Version Tagging + +```bash +# Semantic versioning +v1.0.0 # Major.Minor.Patch +v1.0.1 # Patch release +v1.1.0 # Minor release +v2.0.0 # Major release + +# Pre-release versions +v1.0.0-rc.1 # Release candidate +v1.0.0-beta.1 # Beta release +v1.0.0-alpha.1 # Alpha release +``` + +### 3. Feature Branches + +```bash +# Create feature branch +git checkout -b feature/user-authentication +# ... make changes ... +git add . +git commit -m "feat: add user authentication" +git push origin feature/user-authentication + +# Create PR +# After approval, merge to develop +git checkout develop +git merge feature/user-authentication +git push origin develop +# -> Triggers pipeline + deploy to staging + +# After testing in staging, merge to main +git checkout main +git merge develop +git push origin main +# -> Triggers pipeline + deploy to staging + +# Create production release +git tag -a v1.1.0 -m "Release v1.1.0: Add user authentication" +git push origin v1.1.0 +# -> Triggers pipeline + deploy to production +``` + +### 4. Hotfix Process + +```bash +# Create hotfix branch from main +git checkout -b hotfix/critical-bug main + +# Fix the bug +git add . +git commit -m "fix: critical security vulnerability" + +# Merge to main +git checkout main +git merge hotfix/critical-bug + +# Tag immediately +git tag -a v1.0.1 -m "Hotfix v1.0.1: Security patch" +git push origin main v1.0.1 +# -> Triggers pipeline + deploy to production + +# Merge back to develop +git checkout develop +git merge hotfix/critical-bug +git push origin develop +``` + +## Environment Variables + +### Available in Pipeline + +```bash +CI=woodpecker # Always set +CI_REPO=username/peikarband # Repository name +CI_REPO_LINK=https://git.../peikarband # Repository URL +CI_COMMIT_SHA=a1b2c3d4e5f6... # Full commit hash +CI_COMMIT_BRANCH=main # Branch name +CI_COMMIT_TAG=v1.0.0 # Tag (if triggered by tag) +CI_COMMIT_MESSAGE=feat: new feature # Commit message +CI_PIPELINE_CREATED=2024-01-01T... # Pipeline creation time +CI_PIPELINE_NUMBER=123 # Pipeline number +``` + +### Usage Example + +```bash +# In pipeline step +echo "Building commit ${CI_COMMIT_SHA:0:8} from branch ${CI_COMMIT_BRANCH}" +echo "Image tag: hub.peikarband.ir/peikarband/landing:${CI_COMMIT_SHA:0:8}" +``` + +## Support & Contact + +برای مشکلات و سوالات: +- **Documentation:** این فایل +- **Issues:** GitLab/GitHub Issues +- **Team Contact:** dev@peikarband.ir + +## مراجع + +- [Woodpecker CI Documentation](https://woodpecker-ci.org/docs/intro) +- [Docker Build Best Practices](https://docs.docker.com/develop/dev-best-practices/) +- [Helm Documentation](https://helm.sh/docs/) +- [Kubernetes Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) + diff --git a/helm/.helmignore b/helm/.helmignore deleted file mode 100644 index 898df48..0000000 --- a/helm/.helmignore +++ /dev/null @@ -1,24 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ - diff --git a/helm/peikarband/.helmignore b/helm/peikarband/.helmignore deleted file mode 100644 index 898df48..0000000 --- a/helm/peikarband/.helmignore +++ /dev/null @@ -1,24 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ - diff --git a/helm/peikarband/argocd/README.md b/helm/peikarband/argocd/README.md new file mode 100644 index 0000000..69ae87b --- /dev/null +++ b/helm/peikarband/argocd/README.md @@ -0,0 +1,257 @@ +# ArgoCD Application Manifests + +این پوشه شامل ArgoCD Application manifests برای deployment خودکار با GitOps است. + +## ساختار + +``` +argocd/ +├── application.yaml # Production deployment (namespace: production) +├── application-staging.yaml # Staging deployment (namespace: staging) +├── secrets/ # Kubernetes secrets (DO NOT commit real secrets) +└── README.md # این فایل +``` + +## استفاده + +### 1. Deploy به Production + +```bash +# Apply ArgoCD Application +kubectl apply -f helm/peikarband/argocd/application.yaml + +# Check sync status +argocd app get peikarband-landing-prod + +# Sync manually if needed +argocd app sync peikarband-landing-prod + +# Watch deployment +kubectl get pods -n production -w +``` + +### 2. Deploy به Staging + +```bash +# Apply ArgoCD Application +kubectl apply -f helm/peikarband/argocd/application-staging.yaml + +# Check sync status +argocd app get peikarband-landing-staging + +# Sync manually +argocd app sync peikarband-landing-staging +``` + +### 3. Update Image Tag + +#### روش اول: از طریق ArgoCD UI +1. باز کردن ArgoCD UI +2. رفتن به Application مورد نظر +3. کلیک روی "Parameters" +4. تغییر `image.tag` به tag جدید +5. کلیک روی "Sync" + +#### روش دوم: از طریق CLI + +```bash +# Update production +argocd app set peikarband-landing-prod \ + -p image.tag=v1.2.3 + +# Update staging +argocd app set peikarband-landing-staging \ + -p image.tag=develop +``` + +#### روش سوم: تغییر در Git (GitOps روش اصلی) + +```bash +# Update values-production.yaml +vim helm/peikarband/values-production.yaml +# Change image.tag value + +# Commit & Push +git add helm/peikarband/values-production.yaml +git commit -m "chore: update image to v1.2.3" +git push origin main + +# ArgoCD will auto-sync (if automated sync enabled) +``` + +## تنظیمات مهم + +### Auto-Sync + +Her دو application روی `automated sync` تنظیم شده‌اند: +- **prune**: true → منابع اضافی حذف میشن +- **selfHeal**: true → تغییرات manual برگشت میخورن +- **allowEmpty**: false → deploy خالی مجاز نیست + +### Sync Options + +- **CreateNamespace**: true → namespace خودکار ساخته میشه +- **PrunePropagationPolicy**: foreground → منابع به ترتیب حذف میشن +- **PruneLast**: true → prune در آخر انجام میشه + +### Retry Policy + +در صورت شکست: +- تا 5 بار تلاش مجدد +- با backoff exponential (5s, 10s, 20s, 40s, 80s) +- حداکثر 3 دقیقه delay + +## Secrets Management + +⚠️ **هشدار امنیتی:** + +Secrets نباید در Git commit بشن! از یکی از روش‌های زیر استفاده کنید: + +### روش 1: Manual Secret Creation + +```bash +# Create registry secret +kubectl create secret docker-registry hub-registry-secret \ + --docker-server=hub.peikarband.ir \ + --docker-username=admin \ + --docker-password=YOUR_PASSWORD \ + --namespace=production + +# Create application secrets +kubectl create secret generic peikarband-prod-secrets \ + --from-literal=db-username=peikarband \ + --from-literal=db-password=YOUR_DB_PASSWORD \ + --from-literal=redis-password=YOUR_REDIS_PASSWORD \ + --namespace=production +``` + +### روش 2: Sealed Secrets (پیشنهاد شده) + +```bash +# Install sealed-secrets controller +kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml + +# Create sealed secret +kubeseal --format=yaml < secret.yaml > sealed-secret.yaml + +# Commit sealed-secret.yaml (امن است) +git add helm/peikarband/argocd/secrets/sealed-secret.yaml +git commit -m "chore: add sealed secrets" +``` + +### روش 3: External Secrets Operator + +```bash +# Install external-secrets +helm install external-secrets external-secrets/external-secrets \ + --namespace external-secrets-system \ + --create-namespace + +# Create SecretStore +kubectl apply -f argocd/secrets/secret-store.yaml + +# Create ExternalSecret +kubectl apply -f argocd/secrets/external-secret.yaml +``` + +## Health Checks + +ArgoCD health checks: +- **Deployment**: Ready replicas == Desired replicas +- **Service**: Endpoint موجود باشه +- **Ingress**: Backend service موجود باشه +- **HPA**: Status normal باشه + +## Rollback + +در صورت مشکل: + +```bash +# List revisions +argocd app history peikarband-landing-prod + +# Rollback to specific revision +argocd app rollback peikarband-landing-prod 5 + +# Or rollback to previous +argocd app rollback peikarband-landing-prod +``` + +## Monitoring + +```bash +# Watch application status +argocd app watch peikarband-landing-prod + +# Get detailed status +argocd app get peikarband-landing-prod --refresh + +# Show sync differences +argocd app diff peikarband-landing-prod + +# View logs +kubectl logs -n production -l app.kubernetes.io/name=peikarband -f +``` + +## Troubleshooting + +### App won't sync + +```bash +# Check sync status +argocd app get peikarband-landing-prod + +# Force refresh +argocd app get peikarband-landing-prod --refresh --hard-refresh + +# Delete and recreate +argocd app delete peikarband-landing-prod +kubectl apply -f helm/peikarband/argocd/application.yaml +``` + +### Pods not starting + +```bash +# Check pod status +kubectl get pods -n production + +# Check pod logs +kubectl logs -n production + +# Describe pod for events +kubectl describe pod -n production + +# Check image pull secrets +kubectl get secrets -n production +``` + +### Health check failing + +```bash +# Check service endpoints +kubectl get endpoints -n production + +# Test health endpoint +kubectl port-forward -n production svc/peikarband 8000:8000 +curl http://localhost:8000/ping +``` + +## CI/CD Integration + +در Woodpecker/GitHub Actions: + +```yaml +- name: Update ArgoCD Image + image: argoproj/argocd:latest + commands: + - argocd login argocd.peikarband.ir --username admin --password $ARGOCD_PASSWORD + - argocd app set peikarband-landing-prod -p image.tag=${CI_COMMIT_SHA:0:8} + - argocd app sync peikarband-landing-prod --timeout 300 +``` + +## مستندات بیشتر + +- [ArgoCD Documentation](https://argo-cd.readthedocs.io/) +- [Helm Best Practices](https://helm.sh/docs/chart_best_practices/) +- [Kubernetes Secrets Management](https://kubernetes.io/docs/concepts/configuration/secret/) + diff --git a/argocd/application-staging.yaml b/helm/peikarband/argocd/application-staging.yaml similarity index 70% rename from argocd/application-staging.yaml rename to helm/peikarband/argocd/application-staging.yaml index 4b91852..4f907cb 100644 --- a/argocd/application-staging.yaml +++ b/helm/peikarband/argocd/application-staging.yaml @@ -1,36 +1,31 @@ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: - name: peikarband-staging + name: peikarband-landing-staging namespace: argocd - annotations: - notifications.argoproj.io/subscribe.on-deployed.telegram: "" - notifications.argoproj.io/subscribe.on-sync-failed.telegram: "" finalizers: - resources-finalizer.argocd.argoproj.io - labels: - app: peikarband - environment: staging spec: project: default source: - repoURL: https://git.peikarband.ir/ehsan-minadd/peikarband.git + repoURL: http://git.peikarband.ir/ehsan-minadd/peikarband targetRevision: develop path: helm/peikarband helm: releaseName: peikarband-staging valueFiles: + - values.yaml - values-staging.yaml parameters: - - name: image.repository - value: harbor.peikarband.ir/peikarband/landing - name: image.tag value: develop + - name: image.repository + value: hub.peikarband.ir/peikarband/landing destination: server: https://kubernetes.default.svc - namespace: peikarband-staging + namespace: staging syncPolicy: automated: @@ -50,6 +45,7 @@ spec: revisionHistoryLimit: 10 + # Health assessment ignoreDifferences: - group: apps kind: Deployment diff --git a/argocd/application.yaml b/helm/peikarband/argocd/application.yaml similarity index 59% rename from argocd/application.yaml rename to helm/peikarband/argocd/application.yaml index e2cc564..eb8c759 100644 --- a/argocd/application.yaml +++ b/helm/peikarband/argocd/application.yaml @@ -1,37 +1,31 @@ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: - name: peikarband + name: peikarband-landing-prod namespace: argocd - annotations: - notifications.argoproj.io/subscribe.on-deployed.telegram: "" - notifications.argoproj.io/subscribe.on-health-degraded.telegram: "" - notifications.argoproj.io/subscribe.on-sync-failed.telegram: "" finalizers: - resources-finalizer.argocd.argoproj.io - labels: - app: peikarband - environment: production spec: project: default source: - repoURL: https://git.peikarband.ir/ehsan-minadd/peikarband.git + repoURL: http://git.peikarband.ir/ehsan-minadd/peikarband targetRevision: main path: helm/peikarband helm: releaseName: peikarband valueFiles: + - values.yaml - values-production.yaml parameters: - - name: image.repository - value: harbor.peikarband.ir/peikarband/landing - name: image.tag - value: latest # This will be updated by CI/CD + value: latest + - name: image.repository + value: hub.peikarband.ir/peikarband/landing destination: server: https://kubernetes.default.svc - namespace: peikarband + namespace: production syncPolicy: automated: @@ -42,7 +36,6 @@ spec: - CreateNamespace=true - PrunePropagationPolicy=foreground - PruneLast=true - - ApplyOutOfSyncOnly=true retry: limit: 5 backoff: @@ -52,13 +45,10 @@ spec: revisionHistoryLimit: 10 + # Health assessment ignoreDifferences: - group: apps kind: Deployment jsonPointers: - /spec/replicas - - group: apps - kind: StatefulSet - jsonPointers: - - /spec/replicas diff --git a/logo.png b/logo.png deleted file mode 100644 index b4cea4b..0000000 Binary files a/logo.png and /dev/null differ diff --git a/peikarband/README.md b/peikarband/README.md new file mode 100644 index 0000000..8e9c333 --- /dev/null +++ b/peikarband/README.md @@ -0,0 +1,222 @@ +# پیکربند - پلتفرم جامع مدیریت هاستینگ و زیرساخت ابری + +## 📖 درباره پروژه + +پیکربند یک پلتفرم حرفه‌ای برای مدیریت هاستینگ، سرورهای ابری، دامین و خدمات DevOps است. این پلتفرم با الهام از سرویس‌هایی مانند Cloudways، DigitalOcean و پارس پک طراحی شده است. + +## 🏗️ معماری + +این پروژه بر اساس **Clean Architecture** و اصول **SOLID** طراحی شده است: + +- **Domain Layer**: منطق کسب‌وکار اصلی +- **Application Layer**: موارد استفاده (Use Cases) +- **Infrastructure Layer**: پیاده‌سازی‌های فنی +- **Presentation Layer**: رابط کاربری (Reflex) + +## 🚀 تکنولوژی‌ها + +- **Frontend/Backend**: Python Reflex +- **Database**: PostgreSQL + SQLAlchemy +- **Cache**: Redis +- **Task Queue**: Celery +- **Testing**: pytest +- **Code Quality**: black, flake8, mypy, isort + +## 📋 پیش‌نیازها + +- Python 3.11+ +- PostgreSQL 14+ +- Redis 7+ +- Node.js 18+ (برای Reflex) + +## 🛠️ نصب و راه‌اندازی + +### 1. کلون کردن پروژه + +```bash +git clone https://github.com/yourusername/peikarband.git +cd peikarband +``` + +### 2. ایجاد محیط مجازی + +```bash +python -m venv venv +source venv/bin/activate # On Windows: venv\Scripts\activate +``` + +### 3. نصب وابستگی‌ها + +```bash +pip install -r requirements.txt +pip install -r requirements-dev.txt # برای توسعه +``` + +### 4. تنظیم Environment Variables + +```bash +cp .env.example .env +# ویرایش .env و تکمیل مقادیر +``` + +### 5. راه‌اندازی دیتابیس + +```bash +# ایجاد دیتابیس +createdb peikarband + +# اجرای migrations +alembic upgrade head +``` + +### 6. اجرای پروژه + +```bash +# توسعه +python -m reflex run + +# یا +make dev +``` + +## 🚢 Deployment + +### با Docker + +```bash +# Build +docker build -t peikarband:latest . + +# Run +docker-compose up -d +``` + +### با Kubernetes/Helm + +```bash +# Deploy +helm upgrade --install peikarband ./deploy/helm/peikarband \ + --namespace production \ + --set image.tag=0.1.0 + +# یا +make k8s-deploy +``` + +📖 [راهنمای کامل Deployment](docs/deployment/kubernetes.md) + +## 📁 ساختار پروژه + +``` +peikarband-landing/ +├── build/ # Build configs (Docker, CI/CD) +├── deploy/ # Deployment configs (Helm, K8s, ArgoCD) +├── config/ # Configuration files +├── tools/ # Scripts و ابزارها +├── assets/ # Static assets +├── src/ # Source code (Clean Architecture) +│ ├── config/ # تنظیمات +│ ├── core/ # هسته اصلی (Domain + Application) +│ ├── infrastructure/ # پیاده‌سازی‌های فنی +│ ├── presentation/ # رابط کاربری (Reflex) +│ └── shared/ # کدهای مشترک +├── tests/ # تست‌ها +├── docs/ # مستندات کامل +└── data/ # Local data (gitignored) +``` + +📖 [ساختار کامل پروژه](docs/PROJECT_STRUCTURE.md) + +## 🧪 تست + +```bash +# اجرای همه تست‌ها +pytest + +# با coverage +pytest --cov=src tests/ + +# تست‌های خاص +pytest tests/unit/ +pytest tests/integration/ +``` + +## 📝 کدنویسی + +### استانداردها + +- **PEP 8**: استاندارد کدنویسی Python +- **PEP 20**: Zen of Python +- **Type Hints**: همه جا استفاده شود +- **Docstrings**: Google Style + +### ابزارهای کیفیت کد + +```bash +# Format +black src/ + +# Linting +flake8 src/ + +# Type checking +mypy src/ + +# Import sorting +isort src/ +``` + +### Pre-commit Hooks + +```bash +pre-commit install +pre-commit run --all-files +``` + +## 📚 مستندات + +مستندات کامل در پوشه `docs/` موجود است: + +- [Handbook](docs/handbook.md): راهنمای جامع پروژه +- [Architecture](docs/architecture/): معماری سیستم +- [Development](docs/development/): راهنمای توسعه +- [API Reference](docs/api/): مستندات API + +## 🔐 امنیت + +- همه پسوردها با bcrypt hash می‌شوند +- استفاده از JWT برای authentication +- پشتیبانی از 2FA +- اطلاعات حساس رمزنگاری می‌شوند + +## 🤝 مشارکت + +برای مشارکت در پروژه: + +1. Fork کنید +2. Branch جدید بسازید (`git checkout -b feature/amazing-feature`) +3. Commit کنید (`git commit -m 'feat: add amazing feature'`) +4. Push کنید (`git push origin feature/amazing-feature`) +5. Pull Request بسازید + +## 📄 لایسنس + +این پروژه تحت لایسنس MIT منتشر شده است. + +## 👥 تیم + +- Lead Developer: [Your Name] +- Architecture: Clean Architecture +- Methodology: Agile/Scrum + +## 📞 تماس + +- Website: https://peikarband.ir +- Email: support@peikarband.ir +- Telegram: @peikarband + +--- + +**نسخه**: 0.1.0 +**آخرین بروزرسانی**: 2025-01-24 + diff --git a/peikarband/__init__.py b/peikarband/__init__.py deleted file mode 100644 index 98996f5..0000000 --- a/peikarband/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Peikarband application package.""" - -from .peikarband import app - -__all__ = ["app"] - diff --git a/assets/banner-3.gif b/peikarband/assets/banner-3.gif similarity index 100% rename from assets/banner-3.gif rename to peikarband/assets/banner-3.gif diff --git a/assets/custom.css b/peikarband/assets/custom.css similarity index 100% rename from assets/custom.css rename to peikarband/assets/custom.css diff --git a/assets/hero-person.svg b/peikarband/assets/hero-person.svg similarity index 100% rename from assets/hero-person.svg rename to peikarband/assets/hero-person.svg diff --git a/assets/hero-servers.svg b/peikarband/assets/hero-servers.svg similarity index 100% rename from assets/hero-servers.svg rename to peikarband/assets/hero-servers.svg diff --git a/assets/hero-shield.svg b/peikarband/assets/hero-shield.svg similarity index 100% rename from assets/hero-shield.svg rename to peikarband/assets/hero-shield.svg diff --git a/assets/logo.png b/peikarband/assets/logo.png similarity index 100% rename from assets/logo.png rename to peikarband/assets/logo.png diff --git a/assets/wordpress-logo.gif b/peikarband/assets/wordpress-logo.gif similarity index 100% rename from assets/wordpress-logo.gif rename to peikarband/assets/wordpress-logo.gif diff --git a/src/presentation/web/assets/wordpress.gif b/peikarband/assets/wordpress.gif similarity index 100% rename from src/presentation/web/assets/wordpress.gif rename to peikarband/assets/wordpress.gif diff --git a/alembic.ini b/peikarband/config/alembic.ini similarity index 100% rename from alembic.ini rename to peikarband/config/alembic.ini diff --git a/mypy.ini b/peikarband/config/mypy.ini similarity index 100% rename from mypy.ini rename to peikarband/config/mypy.ini diff --git a/pytest.ini b/peikarband/config/pytest.ini similarity index 100% rename from pytest.ini rename to peikarband/config/pytest.ini diff --git a/rxconfig.py b/peikarband/config/reflex.config.py similarity index 100% rename from rxconfig.py rename to peikarband/config/reflex.config.py diff --git a/peikarband/docs/PROJECT_STRUCTURE.md b/peikarband/docs/PROJECT_STRUCTURE.md new file mode 100644 index 0000000..c473e68 --- /dev/null +++ b/peikarband/docs/PROJECT_STRUCTURE.md @@ -0,0 +1,360 @@ +# ساختار پروژه پیکربند - Landing Page + +## 📁 ساختار کلی (بازسازی شده) + +``` +peikarband-landing/ +├── README.md # Main project documentation +├── requirements.txt # Production dependencies +├── requirements-dev.txt # Development dependencies +├── Makefile # Build automation commands +├── rxconfig.py # Reflex config loader (imports from config/) +├── .gitignore +│ +├── build/ # 🔨 همه چیز مربوط به Build +│ ├── docker/ +│ │ ├── Dockerfile # Main application Dockerfile +│ │ ├── Dockerfile.base # Base image (reference) +│ │ ├── docker-compose.yml # Local development setup +│ │ └── .dockerignore +│ └── ci/ +│ └── woodpecker.yml # CI/CD pipeline configuration +│ +├── deploy/ # 🚀 همه چیز مربوط به Deployment +│ ├── helm/ +│ │ └── peikarband/ # Helm chart +│ │ ├── Chart.yaml +│ │ ├── templates/ # K8s resource templates +│ │ ├── values.yaml # Default values +│ │ ├── values-production.yaml +│ │ └── values-staging.yaml +│ ├── kubernetes/ +│ │ └── secrets-template.yaml # K8s manifest templates +│ └── argocd/ # ArgoCD GitOps configs +│ ├── application.yaml +│ ├── application-staging.yaml +│ ├── README.md +│ └── secrets/ +│ +├── config/ # ⚙️ همه Configuration Files +│ ├── alembic.ini # Database migration config +│ ├── mypy.ini # Type checking config +│ ├── pytest.ini # Test configuration +│ └── reflex.config.py # Reflex app configuration +│ +├── tools/ # 🔧 Scripts و ابزارهای کمکی +│ ├── scripts/ +│ │ ├── update-env-json.sh # Runtime config updater +│ │ └── diagnose-502.sh # Diagnostic tools +│ └── setup.py # Package setup +│ +├── assets/ # 🎨 Static Assets (served by Reflex) +│ ├── logo.png +│ ├── banner-3.gif +│ ├── custom.css +│ ├── hero-*.svg +│ └── wordpress*.gif +│ +├── data/ # 💾 Local Data (gitignored) +│ ├── db/ # Local database files +│ ├── cache/ # Cache files +│ └── logs/ # Log files +│ +├── src/ # 💻 Source Code (Clean Architecture) +│ ├── config/ # Application configuration +│ │ ├── settings.py +│ │ ├── database.py +│ │ ├── cache.py +│ │ └── logging.py +│ ├── core/ # Core business logic +│ │ ├── domain/ # Domain layer +│ │ │ ├── entities/ # Domain entities +│ │ │ ├── value_objects/ # Value objects +│ │ │ ├── enums/ # Domain enums +│ │ │ └── exceptions/ # Domain exceptions +│ │ └── application/ # Application layer +│ │ ├── use_cases/ # Use cases +│ │ ├── dto/ # Data Transfer Objects +│ │ ├── interfaces/ # Interfaces/Ports +│ │ └── validators/ # Validators +│ ├── infrastructure/ # Infrastructure layer +│ │ ├── database/ # Database implementation +│ │ │ ├── models/ # SQLAlchemy models +│ │ │ ├── repositories/ # Repository implementations +│ │ │ └── migrations/ # Alembic migrations +│ │ ├── cache/ # Cache implementation (Redis) +│ │ ├── external/ # External API integrations +│ │ │ ├── email/ +│ │ │ ├── sms/ +│ │ │ ├── payment/ +│ │ │ └── providers/ +│ │ ├── security/ # Security implementations +│ │ └── tasks/ # Background tasks (Celery) +│ ├── presentation/ # Presentation layer +│ │ ├── web/ # Reflex web application +│ │ │ ├── pages/ # Reflex pages +│ │ │ ├── components/ # Reusable components +│ │ │ ├── state/ # Application state +│ │ │ └── styles/ # Styling +│ │ └── api/ # REST API endpoints (if needed) +│ │ ├── routes/ +│ │ └── middleware/ +│ └── shared/ # Shared utilities +│ ├── events/ # Event system +│ └── messaging/ # Message bus +│ +├── tests/ # 🧪 Test Suites +│ ├── unit/ # Unit tests +│ │ ├── core/ +│ │ └── infrastructure/ +│ ├── integration/ # Integration tests +│ │ ├── database/ +│ │ └── external/ +│ ├── e2e/ # End-to-end tests +│ │ └── scenarios/ +│ ├── fixtures/ # Test fixtures +│ └── conftest.py # Pytest configuration +│ +├── docs/ # 📚 Documentation +│ ├── api/ # API documentation +│ ├── architecture/ # Architecture docs +│ │ ├── overview.md +│ │ └── database-strategy.md +│ ├── deployment/ # Deployment guides +│ │ ├── DEPLOYMENT_CHECKLIST.md +│ │ ├── DEPLOYMENT_QUICK_START.md +│ │ ├── PRODUCTION_DEPLOYMENT.md +│ │ ├── CHANGELOG-DEPLOYMENT.md +│ │ └── kubernetes.md +│ ├── development/ # Development guides +│ │ ├── setup.md +│ │ ├── coding-standards.md +│ │ └── git-workflow.md +│ ├── changelog/ # Change logs +│ │ ├── CHANGELOG.md +│ │ ├── migrations.md +│ │ └── known-issues.md +│ ├── operations/ # Operations docs +│ ├── handbook.md # Complete handbook +│ └── PROJECT_STRUCTURE.md # This file +│ +└── tmp/ # Temporary files (gitignored) +``` + +## 🎯 معماری جدید - Separation of Concerns + +### 1. `build/` - Build Configurations +**هدف**: جداسازی همه چیز مربوط به build process + +- **`build/docker/`**: تمام فایل‌های Docker + - Multi-stage Dockerfile با optimization + - Docker Compose برای development + - .dockerignore + +- **`build/ci/`**: CI/CD configurations + - Woodpecker CI pipeline + - سایر CI configs (GitHub Actions, GitLab CI) + +**مزایا**: +- ✅ Root directory تمیزتر +- ✅ Build configs مدیریت شده در یک مکان +- ✅ CI/CD configs جدا از کد + +### 2. `deploy/` - Deployment Configurations +**هدف**: تمرکز همه deployment configs + +- **`deploy/helm/`**: Helm charts + - Production و Staging values + - Templates برای تمام K8s resources + +- **`deploy/kubernetes/`**: Raw K8s manifests + - Secret templates + - Custom resources + +- **`deploy/argocd/`**: ArgoCD GitOps + - Application definitions + - Sync policies + +**مزایا**: +- ✅ یک مکان برای همه deployment +- ✅ واضح برای DevOps engineers +- ✅ جداسازی از source code + +### 3. `config/` - Configuration Files +**هدف**: تمرکز همه config files + +- `alembic.ini`: Database migrations +- `mypy.ini`: Type checking +- `pytest.ini`: Testing +- `reflex.config.py`: Reflex framework + +**مزایا**: +- ✅ Root directory خلوت‌تر +- ✅ Configs به راحتی پیدا می‌شوند +- ✅ مدیریت بهتر + +### 4. `tools/` - Utility Scripts +**هدف**: جداسازی scripts و ابزارها + +- Runtime scripts +- Diagnostic tools +- Setup utilities + +**مزایا**: +- ✅ Scripts منظم و دسته‌بندی شده +- ✅ جدا از source code + +### 5. `assets/` - Consolidated Assets +**هدف**: یک مکان واحد برای همه static assets + +**قبلاً**: Assets پراکنده در `assets/` و `src/presentation/web/assets/` +**الان**: همه در `assets/` (served directly by Reflex) + +**فایل‌های موجود**: +- `logo.png` - لوگوی پیکربند +- `banner-3.gif` - Banner animation +- `wordpress-logo.gif` - WordPress logo +- `hero-*.svg` - Hero section icons +- `custom.css` - Custom styles + +**استفاده در کد**: +```python +rx.image(src="/logo.png") # Reflex serves from /assets +``` + +**مزایا**: +- ✅ No duplication +- ✅ یک منبع حقیقت +- ✅ مدیریت آسان‌تر +- ✅ سازگار با Reflex + +### 6. `data/` - Local Data (gitignored) +**هدف**: Local development data + +- `data/db/`: SQLite و database files +- `data/cache/`: Redis dumps +- `data/logs/`: Log files + +**مزایا**: +- ✅ Data جدا از code +- ✅ .gitignore شده +- ✅ Clean repository + +## 🔗 ارتباط با پروژه‌های دیگر + +### Base Image Repository +- **Repo**: `peikarband/base` +- **Registry**: `hub.peikarband.ir/peikarband/base:latest` +- **Purpose**: Base image with Python, Node.js, bun, build tools +- **Build**: Separate CI/CD pipeline +- **Usage**: Referenced in `build/docker/Dockerfile` + +### Landing Page (This Repo) +- **Repo**: `peikarband/landing` +- **Registry**: `hub.peikarband.ir/peikarband/landing:latest` +- **Purpose**: Landing page application +- **Dependencies**: Uses base image + +## 📝 فایل‌های Root (Minimal) + +### ضروری +- `README.md`: Main documentation +- `requirements.txt`: Dependencies +- `Makefile`: Build commands +- `rxconfig.py`: Reflex config loader +- `.gitignore`: Git ignore rules + +### حذف شده از Root +- ❌ `Dockerfile` → `build/docker/` +- ❌ `docker-compose.yml` → `build/docker/` +- ❌ `.woodpecker.yml` → `build/ci/` +- ❌ `alembic.ini` → `config/` +- ❌ `pytest.ini` → `config/` +- ❌ `mypy.ini` → `config/` +- ❌ `scripts/` → `tools/scripts/` +- ❌ `setup.py` → `tools/` +- ❌ `helm/` → `deploy/helm/` +- ❌ `argocd/` → `deploy/argocd/` +- ❌ Duplicate assets → `assets/static/` + +## 🎯 Best Practices + +### Root Directory +- ✅ فقط فایل‌های ضروری +- ✅ Config files در `config/` +- ✅ Build files در `build/` +- ✅ Deploy files در `deploy/` + +### Source Code (`src/`) +- ✅ Clean Architecture layers +- ✅ Separation of concerns +- ✅ SOLID principles + +### Documentation +- ✅ همه docs در `docs/` +- ✅ دسته‌بندی منطقی +- ✅ به‌روز و جامع + +### Deployment +- ✅ Helm charts محیط‌محور +- ✅ ArgoCD GitOps +- ✅ Secrets جدا از code + +### Testing +- ✅ Unit/Integration/E2E جدا +- ✅ Fixtures منظم +- ✅ Coverage بالا + +## 🚀 مزایای معماری جدید + +1. **Clarity** ✨ + - واضح است که هر فایل کجا باشد + - Navigation آسان‌تر + +2. **Maintainability** 🔧 + - نگهداری آسان‌تر + - Onboarding سریع‌تر + +3. **Scalability** 📈 + - اضافه کردن configs جدید ساده + - مقیاس‌پذیری بهتر + +4. **Professional** 💼 + - استاندارد enterprise projects + - Best practices معماری + +5. **Developer Experience** 👨‍💻 + - کم‌تر سردرگم + - Productivity بالاتر + +## 📊 مقایسه قبل و بعد + +### قبل +``` +root/ +├── 15+ config files 😰 +├── Docker files +├── CI configs +├── helm/ +├── argocd/ +├── scripts/ +├── assets/ (duplicate!) +└── src/ +``` + +### بعد +``` +root/ +├── 4 essential files only 😌 +├── build/ (organized) +├── deploy/ (organized) +├── config/ (organized) +├── tools/ (organized) +├── assets/static/ (consolidated) +└── src/ (clean) +``` + +--- + +**آخرین بروزرسانی**: 2025-01-30 +**نسخه معماری**: 2.0 (Restructured) diff --git a/docs/architecture/database-strategy.md b/peikarband/docs/architecture/database-strategy.md similarity index 100% rename from docs/architecture/database-strategy.md rename to peikarband/docs/architecture/database-strategy.md diff --git a/docs/architecture/overview.md b/peikarband/docs/architecture/overview.md similarity index 100% rename from docs/architecture/overview.md rename to peikarband/docs/architecture/overview.md diff --git a/docs/changelog/CHANGELOG.md b/peikarband/docs/changelog/CHANGELOG.md similarity index 100% rename from docs/changelog/CHANGELOG.md rename to peikarband/docs/changelog/CHANGELOG.md diff --git a/docs/changelog/known-issues.md b/peikarband/docs/changelog/known-issues.md similarity index 100% rename from docs/changelog/known-issues.md rename to peikarband/docs/changelog/known-issues.md diff --git a/docs/changelog/migrations.md b/peikarband/docs/changelog/migrations.md similarity index 100% rename from docs/changelog/migrations.md rename to peikarband/docs/changelog/migrations.md diff --git a/CHANGELOG-DEPLOYMENT.md b/peikarband/docs/deployment/CHANGELOG-DEPLOYMENT.md similarity index 100% rename from CHANGELOG-DEPLOYMENT.md rename to peikarband/docs/deployment/CHANGELOG-DEPLOYMENT.md diff --git a/DEPLOYMENT_CHECKLIST.md b/peikarband/docs/deployment/DEPLOYMENT_CHECKLIST.md similarity index 100% rename from DEPLOYMENT_CHECKLIST.md rename to peikarband/docs/deployment/DEPLOYMENT_CHECKLIST.md diff --git a/DEPLOYMENT_QUICK_START.md b/peikarband/docs/deployment/DEPLOYMENT_QUICK_START.md similarity index 100% rename from DEPLOYMENT_QUICK_START.md rename to peikarband/docs/deployment/DEPLOYMENT_QUICK_START.md diff --git a/docs/deployment/PRODUCTION_DEPLOYMENT.md b/peikarband/docs/deployment/PRODUCTION_DEPLOYMENT.md similarity index 100% rename from docs/deployment/PRODUCTION_DEPLOYMENT.md rename to peikarband/docs/deployment/PRODUCTION_DEPLOYMENT.md diff --git a/docs/deployment/kubernetes.md b/peikarband/docs/deployment/kubernetes.md similarity index 100% rename from docs/deployment/kubernetes.md rename to peikarband/docs/deployment/kubernetes.md diff --git a/docs/deployment/quickstart.md b/peikarband/docs/deployment/quickstart.md similarity index 100% rename from docs/deployment/quickstart.md rename to peikarband/docs/deployment/quickstart.md diff --git a/docs/development/coding-standards.md b/peikarband/docs/development/coding-standards.md similarity index 100% rename from docs/development/coding-standards.md rename to peikarband/docs/development/coding-standards.md diff --git a/docs/development/git-workflow.md b/peikarband/docs/development/git-workflow.md similarity index 100% rename from docs/development/git-workflow.md rename to peikarband/docs/development/git-workflow.md diff --git a/docs/development/setup.md b/peikarband/docs/development/setup.md similarity index 100% rename from docs/development/setup.md rename to peikarband/docs/development/setup.md diff --git a/docs/handbook.md b/peikarband/docs/handbook.md similarity index 100% rename from docs/handbook.md rename to peikarband/docs/handbook.md diff --git a/peikarband/peikarband.py b/peikarband/peikarband.py deleted file mode 100644 index b98ab29..0000000 --- a/peikarband/peikarband.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Peikarband Application Entry Point - -This is the main application file that Reflex uses to run the app. -""" - -import reflex as rx -from src.presentation.web.pages.landing.index import index -from src.presentation.api.routes.health import ( - ping_endpoint, - health_endpoint, - ready_endpoint, - live_endpoint, -) - -# Create the app -app = rx.App() - -# Add landing page -app.add_page(index, route="/") - -# Add health check pages (for Kubernetes probes) -# These return JSON responses for monitoring -@rx.page(route="/ping") -def ping(): - """Basic health check endpoint""" - data = ping_endpoint() - return rx.box( - rx.text(str(data)), - style={"whiteSpace": "pre"} - ) - -@rx.page(route="/health") -def health(): - """Detailed health check endpoint""" - data = health_endpoint() - return rx.box( - rx.text(str(data)), - style={"whiteSpace": "pre"} - ) - -@rx.page(route="/ready") -def ready(): - """Readiness probe endpoint""" - data = ready_endpoint() - return rx.box( - rx.text(str(data)), - style={"whiteSpace": "pre"} - ) - -@rx.page(route="/live") -def live(): - """Liveness probe endpoint""" - data = live_endpoint() - return rx.box( - rx.text(str(data)), - style={"whiteSpace": "pre"} - ) diff --git a/requirements-dev.txt b/peikarband/requirements-dev.txt similarity index 100% rename from requirements-dev.txt rename to peikarband/requirements-dev.txt diff --git a/requirements.txt b/peikarband/requirements.txt similarity index 100% rename from requirements.txt rename to peikarband/requirements.txt diff --git a/peikarband/rxconfig.py b/peikarband/rxconfig.py new file mode 100644 index 0000000..95486f8 --- /dev/null +++ b/peikarband/rxconfig.py @@ -0,0 +1,27 @@ +"""Reflex configuration file. + +This file configures the Reflex application settings. +""" + +import os +import reflex as rx + +# Environment-aware configuration +API_URL = os.getenv("API_URL", "http://localhost:8000") +FRONTEND_PORT = int(os.getenv("FRONTEND_PORT", "3000")) +BACKEND_PORT = int(os.getenv("BACKEND_PORT", "8000")) +DB_URL = os.getenv("DATABASE_URL", "sqlite:////app/data/reflex.db") + +config = rx.Config( + app_name="peikarband", + api_url=API_URL, + frontend_port=FRONTEND_PORT, + backend_port=BACKEND_PORT, + db_url=DB_URL, + disable_plugins=["reflex.plugins.sitemap.SitemapPlugin"], + stylesheets=[ + "https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap", + "https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css", + ], +) + diff --git a/src/__init__.py b/peikarband/src/__init__.py similarity index 100% rename from src/__init__.py rename to peikarband/src/__init__.py diff --git a/src/config/__init__.py b/peikarband/src/config/__init__.py similarity index 100% rename from src/config/__init__.py rename to peikarband/src/config/__init__.py diff --git a/src/config/cache.py b/peikarband/src/config/cache.py similarity index 100% rename from src/config/cache.py rename to peikarband/src/config/cache.py diff --git a/src/config/database.py b/peikarband/src/config/database.py similarity index 100% rename from src/config/database.py rename to peikarband/src/config/database.py diff --git a/src/config/environments/__init__.py b/peikarband/src/config/environments/__init__.py similarity index 100% rename from src/config/environments/__init__.py rename to peikarband/src/config/environments/__init__.py diff --git a/src/config/logging.py b/peikarband/src/config/logging.py similarity index 100% rename from src/config/logging.py rename to peikarband/src/config/logging.py diff --git a/src/config/settings.py b/peikarband/src/config/settings.py similarity index 100% rename from src/config/settings.py rename to peikarband/src/config/settings.py diff --git a/src/core/__init__.py b/peikarband/src/core/__init__.py similarity index 100% rename from src/core/__init__.py rename to peikarband/src/core/__init__.py diff --git a/src/core/application/__init__.py b/peikarband/src/core/application/__init__.py similarity index 100% rename from src/core/application/__init__.py rename to peikarband/src/core/application/__init__.py diff --git a/src/core/application/dto/__init__.py b/peikarband/src/core/application/dto/__init__.py similarity index 100% rename from src/core/application/dto/__init__.py rename to peikarband/src/core/application/dto/__init__.py diff --git a/src/core/application/interfaces/__init__.py b/peikarband/src/core/application/interfaces/__init__.py similarity index 100% rename from src/core/application/interfaces/__init__.py rename to peikarband/src/core/application/interfaces/__init__.py diff --git a/src/core/application/interfaces/providers/__init__.py b/peikarband/src/core/application/interfaces/providers/__init__.py similarity index 100% rename from src/core/application/interfaces/providers/__init__.py rename to peikarband/src/core/application/interfaces/providers/__init__.py diff --git a/src/core/application/interfaces/repositories/__init__.py b/peikarband/src/core/application/interfaces/repositories/__init__.py similarity index 100% rename from src/core/application/interfaces/repositories/__init__.py rename to peikarband/src/core/application/interfaces/repositories/__init__.py diff --git a/src/core/application/interfaces/services/__init__.py b/peikarband/src/core/application/interfaces/services/__init__.py similarity index 100% rename from src/core/application/interfaces/services/__init__.py rename to peikarband/src/core/application/interfaces/services/__init__.py diff --git a/src/core/application/use_cases/__init__.py b/peikarband/src/core/application/use_cases/__init__.py similarity index 100% rename from src/core/application/use_cases/__init__.py rename to peikarband/src/core/application/use_cases/__init__.py diff --git a/src/core/application/use_cases/auth/__init__.py b/peikarband/src/core/application/use_cases/auth/__init__.py similarity index 100% rename from src/core/application/use_cases/auth/__init__.py rename to peikarband/src/core/application/use_cases/auth/__init__.py diff --git a/src/core/application/use_cases/billing/__init__.py b/peikarband/src/core/application/use_cases/billing/__init__.py similarity index 100% rename from src/core/application/use_cases/billing/__init__.py rename to peikarband/src/core/application/use_cases/billing/__init__.py diff --git a/src/core/application/use_cases/servers/__init__.py b/peikarband/src/core/application/use_cases/servers/__init__.py similarity index 100% rename from src/core/application/use_cases/servers/__init__.py rename to peikarband/src/core/application/use_cases/servers/__init__.py diff --git a/src/core/application/use_cases/services/__init__.py b/peikarband/src/core/application/use_cases/services/__init__.py similarity index 100% rename from src/core/application/use_cases/services/__init__.py rename to peikarband/src/core/application/use_cases/services/__init__.py diff --git a/src/core/application/validators/__init__.py b/peikarband/src/core/application/validators/__init__.py similarity index 100% rename from src/core/application/validators/__init__.py rename to peikarband/src/core/application/validators/__init__.py diff --git a/src/core/domain/__init__.py b/peikarband/src/core/domain/__init__.py similarity index 100% rename from src/core/domain/__init__.py rename to peikarband/src/core/domain/__init__.py diff --git a/src/core/domain/entities/__init__.py b/peikarband/src/core/domain/entities/__init__.py similarity index 100% rename from src/core/domain/entities/__init__.py rename to peikarband/src/core/domain/entities/__init__.py diff --git a/src/core/domain/entities/base.py b/peikarband/src/core/domain/entities/base.py similarity index 100% rename from src/core/domain/entities/base.py rename to peikarband/src/core/domain/entities/base.py diff --git a/src/core/domain/enums/__init__.py b/peikarband/src/core/domain/enums/__init__.py similarity index 100% rename from src/core/domain/enums/__init__.py rename to peikarband/src/core/domain/enums/__init__.py diff --git a/src/core/domain/exceptions/__init__.py b/peikarband/src/core/domain/exceptions/__init__.py similarity index 100% rename from src/core/domain/exceptions/__init__.py rename to peikarband/src/core/domain/exceptions/__init__.py diff --git a/src/core/domain/exceptions/base.py b/peikarband/src/core/domain/exceptions/base.py similarity index 100% rename from src/core/domain/exceptions/base.py rename to peikarband/src/core/domain/exceptions/base.py diff --git a/src/core/domain/exceptions/user_exceptions.py b/peikarband/src/core/domain/exceptions/user_exceptions.py similarity index 100% rename from src/core/domain/exceptions/user_exceptions.py rename to peikarband/src/core/domain/exceptions/user_exceptions.py diff --git a/src/core/domain/value_objects/__init__.py b/peikarband/src/core/domain/value_objects/__init__.py similarity index 100% rename from src/core/domain/value_objects/__init__.py rename to peikarband/src/core/domain/value_objects/__init__.py diff --git a/src/core/domain/value_objects/email.py b/peikarband/src/core/domain/value_objects/email.py similarity index 100% rename from src/core/domain/value_objects/email.py rename to peikarband/src/core/domain/value_objects/email.py diff --git a/src/core/domain/value_objects/money.py b/peikarband/src/core/domain/value_objects/money.py similarity index 100% rename from src/core/domain/value_objects/money.py rename to peikarband/src/core/domain/value_objects/money.py diff --git a/src/core/domain/value_objects/phone.py b/peikarband/src/core/domain/value_objects/phone.py similarity index 100% rename from src/core/domain/value_objects/phone.py rename to peikarband/src/core/domain/value_objects/phone.py diff --git a/src/core/utils/__init__.py b/peikarband/src/core/utils/__init__.py similarity index 100% rename from src/core/utils/__init__.py rename to peikarband/src/core/utils/__init__.py diff --git a/src/infrastructure/__init__.py b/peikarband/src/infrastructure/__init__.py similarity index 100% rename from src/infrastructure/__init__.py rename to peikarband/src/infrastructure/__init__.py diff --git a/src/infrastructure/cache/__init__.py b/peikarband/src/infrastructure/cache/__init__.py similarity index 100% rename from src/infrastructure/cache/__init__.py rename to peikarband/src/infrastructure/cache/__init__.py diff --git a/src/infrastructure/database/__init__.py b/peikarband/src/infrastructure/database/__init__.py similarity index 100% rename from src/infrastructure/database/__init__.py rename to peikarband/src/infrastructure/database/__init__.py diff --git a/src/infrastructure/database/migrations/__init__.py b/peikarband/src/infrastructure/database/migrations/__init__.py similarity index 100% rename from src/infrastructure/database/migrations/__init__.py rename to peikarband/src/infrastructure/database/migrations/__init__.py diff --git a/src/infrastructure/database/migrations/env.py b/peikarband/src/infrastructure/database/migrations/env.py similarity index 100% rename from src/infrastructure/database/migrations/env.py rename to peikarband/src/infrastructure/database/migrations/env.py diff --git a/src/infrastructure/database/migrations/script.py.mako b/peikarband/src/infrastructure/database/migrations/script.py.mako similarity index 100% rename from src/infrastructure/database/migrations/script.py.mako rename to peikarband/src/infrastructure/database/migrations/script.py.mako diff --git a/src/infrastructure/database/migrations/versions/__init__.py b/peikarband/src/infrastructure/database/migrations/versions/__init__.py similarity index 100% rename from src/infrastructure/database/migrations/versions/__init__.py rename to peikarband/src/infrastructure/database/migrations/versions/__init__.py diff --git a/src/infrastructure/database/models/__init__.py b/peikarband/src/infrastructure/database/models/__init__.py similarity index 100% rename from src/infrastructure/database/models/__init__.py rename to peikarband/src/infrastructure/database/models/__init__.py diff --git a/src/infrastructure/database/models/base.py b/peikarband/src/infrastructure/database/models/base.py similarity index 100% rename from src/infrastructure/database/models/base.py rename to peikarband/src/infrastructure/database/models/base.py diff --git a/src/infrastructure/database/repositories/__init__.py b/peikarband/src/infrastructure/database/repositories/__init__.py similarity index 100% rename from src/infrastructure/database/repositories/__init__.py rename to peikarband/src/infrastructure/database/repositories/__init__.py diff --git a/src/infrastructure/database/repositories/base_repository.py b/peikarband/src/infrastructure/database/repositories/base_repository.py similarity index 100% rename from src/infrastructure/database/repositories/base_repository.py rename to peikarband/src/infrastructure/database/repositories/base_repository.py diff --git a/src/infrastructure/database/unit_of_work.py b/peikarband/src/infrastructure/database/unit_of_work.py similarity index 100% rename from src/infrastructure/database/unit_of_work.py rename to peikarband/src/infrastructure/database/unit_of_work.py diff --git a/src/infrastructure/external/__init__.py b/peikarband/src/infrastructure/external/__init__.py similarity index 100% rename from src/infrastructure/external/__init__.py rename to peikarband/src/infrastructure/external/__init__.py diff --git a/src/infrastructure/external/email/__init__.py b/peikarband/src/infrastructure/external/email/__init__.py similarity index 100% rename from src/infrastructure/external/email/__init__.py rename to peikarband/src/infrastructure/external/email/__init__.py diff --git a/src/infrastructure/external/payment/__init__.py b/peikarband/src/infrastructure/external/payment/__init__.py similarity index 100% rename from src/infrastructure/external/payment/__init__.py rename to peikarband/src/infrastructure/external/payment/__init__.py diff --git a/src/infrastructure/external/providers/__init__.py b/peikarband/src/infrastructure/external/providers/__init__.py similarity index 100% rename from src/infrastructure/external/providers/__init__.py rename to peikarband/src/infrastructure/external/providers/__init__.py diff --git a/src/infrastructure/external/sms/__init__.py b/peikarband/src/infrastructure/external/sms/__init__.py similarity index 100% rename from src/infrastructure/external/sms/__init__.py rename to peikarband/src/infrastructure/external/sms/__init__.py diff --git a/src/infrastructure/logging/__init__.py b/peikarband/src/infrastructure/logging/__init__.py similarity index 100% rename from src/infrastructure/logging/__init__.py rename to peikarband/src/infrastructure/logging/__init__.py diff --git a/src/infrastructure/security/__init__.py b/peikarband/src/infrastructure/security/__init__.py similarity index 100% rename from src/infrastructure/security/__init__.py rename to peikarband/src/infrastructure/security/__init__.py diff --git a/src/infrastructure/tasks/__init__.py b/peikarband/src/infrastructure/tasks/__init__.py similarity index 100% rename from src/infrastructure/tasks/__init__.py rename to peikarband/src/infrastructure/tasks/__init__.py diff --git a/src/presentation/__init__.py b/peikarband/src/presentation/__init__.py similarity index 100% rename from src/presentation/__init__.py rename to peikarband/src/presentation/__init__.py diff --git a/src/presentation/api/__init__.py b/peikarband/src/presentation/api/__init__.py similarity index 100% rename from src/presentation/api/__init__.py rename to peikarband/src/presentation/api/__init__.py diff --git a/src/presentation/api/middleware/__init__.py b/peikarband/src/presentation/api/middleware/__init__.py similarity index 100% rename from src/presentation/api/middleware/__init__.py rename to peikarband/src/presentation/api/middleware/__init__.py diff --git a/src/presentation/api/routes/__init__.py b/peikarband/src/presentation/api/routes/__init__.py similarity index 100% rename from src/presentation/api/routes/__init__.py rename to peikarband/src/presentation/api/routes/__init__.py diff --git a/src/presentation/api/routes/health.py b/peikarband/src/presentation/api/routes/health.py similarity index 100% rename from src/presentation/api/routes/health.py rename to peikarband/src/presentation/api/routes/health.py diff --git a/src/presentation/web/__init__.py b/peikarband/src/presentation/web/__init__.py similarity index 100% rename from src/presentation/web/__init__.py rename to peikarband/src/presentation/web/__init__.py diff --git a/src/presentation/web/components/__init__.py b/peikarband/src/presentation/web/components/__init__.py similarity index 100% rename from src/presentation/web/components/__init__.py rename to peikarband/src/presentation/web/components/__init__.py diff --git a/src/presentation/web/components/cards/__init__.py b/peikarband/src/presentation/web/components/cards/__init__.py similarity index 100% rename from src/presentation/web/components/cards/__init__.py rename to peikarband/src/presentation/web/components/cards/__init__.py diff --git a/src/presentation/web/components/common/__init__.py b/peikarband/src/presentation/web/components/common/__init__.py similarity index 100% rename from src/presentation/web/components/common/__init__.py rename to peikarband/src/presentation/web/components/common/__init__.py diff --git a/src/presentation/web/components/forms/__init__.py b/peikarband/src/presentation/web/components/forms/__init__.py similarity index 100% rename from src/presentation/web/components/forms/__init__.py rename to peikarband/src/presentation/web/components/forms/__init__.py diff --git a/src/presentation/web/pages/__init__.py b/peikarband/src/presentation/web/pages/__init__.py similarity index 100% rename from src/presentation/web/pages/__init__.py rename to peikarband/src/presentation/web/pages/__init__.py diff --git a/src/presentation/web/pages/admin/__init__.py b/peikarband/src/presentation/web/pages/admin/__init__.py similarity index 100% rename from src/presentation/web/pages/admin/__init__.py rename to peikarband/src/presentation/web/pages/admin/__init__.py diff --git a/src/presentation/web/pages/auth/__init__.py b/peikarband/src/presentation/web/pages/auth/__init__.py similarity index 100% rename from src/presentation/web/pages/auth/__init__.py rename to peikarband/src/presentation/web/pages/auth/__init__.py diff --git a/src/presentation/web/pages/dashboard/__init__.py b/peikarband/src/presentation/web/pages/dashboard/__init__.py similarity index 100% rename from src/presentation/web/pages/dashboard/__init__.py rename to peikarband/src/presentation/web/pages/dashboard/__init__.py diff --git a/src/presentation/web/pages/landing/__init__.py b/peikarband/src/presentation/web/pages/landing/__init__.py similarity index 100% rename from src/presentation/web/pages/landing/__init__.py rename to peikarband/src/presentation/web/pages/landing/__init__.py diff --git a/src/presentation/web/pages/landing/index.py b/peikarband/src/presentation/web/pages/landing/index.py similarity index 100% rename from src/presentation/web/pages/landing/index.py rename to peikarband/src/presentation/web/pages/landing/index.py diff --git a/src/presentation/web/state/__init__.py b/peikarband/src/presentation/web/state/__init__.py similarity index 100% rename from src/presentation/web/state/__init__.py rename to peikarband/src/presentation/web/state/__init__.py diff --git a/src/presentation/web/styles/__init__.py b/peikarband/src/presentation/web/styles/__init__.py similarity index 100% rename from src/presentation/web/styles/__init__.py rename to peikarband/src/presentation/web/styles/__init__.py diff --git a/src/shared/__init__.py b/peikarband/src/shared/__init__.py similarity index 100% rename from src/shared/__init__.py rename to peikarband/src/shared/__init__.py diff --git a/src/shared/events/__init__.py b/peikarband/src/shared/events/__init__.py similarity index 100% rename from src/shared/events/__init__.py rename to peikarband/src/shared/events/__init__.py diff --git a/src/shared/messaging/__init__.py b/peikarband/src/shared/messaging/__init__.py similarity index 100% rename from src/shared/messaging/__init__.py rename to peikarband/src/shared/messaging/__init__.py diff --git a/tests/__init__.py b/peikarband/tests/__init__.py similarity index 100% rename from tests/__init__.py rename to peikarband/tests/__init__.py diff --git a/tests/conftest.py b/peikarband/tests/conftest.py similarity index 100% rename from tests/conftest.py rename to peikarband/tests/conftest.py diff --git a/tests/e2e/__init__.py b/peikarband/tests/e2e/__init__.py similarity index 100% rename from tests/e2e/__init__.py rename to peikarband/tests/e2e/__init__.py diff --git a/tests/e2e/scenarios/__init__.py b/peikarband/tests/e2e/scenarios/__init__.py similarity index 100% rename from tests/e2e/scenarios/__init__.py rename to peikarband/tests/e2e/scenarios/__init__.py diff --git a/tests/fixtures/__init__.py b/peikarband/tests/fixtures/__init__.py similarity index 100% rename from tests/fixtures/__init__.py rename to peikarband/tests/fixtures/__init__.py diff --git a/tests/integration/__init__.py b/peikarband/tests/integration/__init__.py similarity index 100% rename from tests/integration/__init__.py rename to peikarband/tests/integration/__init__.py diff --git a/tests/integration/database/__init__.py b/peikarband/tests/integration/database/__init__.py similarity index 100% rename from tests/integration/database/__init__.py rename to peikarband/tests/integration/database/__init__.py diff --git a/tests/integration/external/__init__.py b/peikarband/tests/integration/external/__init__.py similarity index 100% rename from tests/integration/external/__init__.py rename to peikarband/tests/integration/external/__init__.py diff --git a/tests/unit/__init__.py b/peikarband/tests/unit/__init__.py similarity index 100% rename from tests/unit/__init__.py rename to peikarband/tests/unit/__init__.py diff --git a/tests/unit/core/__init__.py b/peikarband/tests/unit/core/__init__.py similarity index 100% rename from tests/unit/core/__init__.py rename to peikarband/tests/unit/core/__init__.py diff --git a/tests/unit/core/application/__init__.py b/peikarband/tests/unit/core/application/__init__.py similarity index 100% rename from tests/unit/core/application/__init__.py rename to peikarband/tests/unit/core/application/__init__.py diff --git a/tests/unit/core/domain/__init__.py b/peikarband/tests/unit/core/domain/__init__.py similarity index 100% rename from tests/unit/core/domain/__init__.py rename to peikarband/tests/unit/core/domain/__init__.py diff --git a/tests/unit/infrastructure/__init__.py b/peikarband/tests/unit/infrastructure/__init__.py similarity index 100% rename from tests/unit/infrastructure/__init__.py rename to peikarband/tests/unit/infrastructure/__init__.py diff --git a/scripts/diagnose-502.sh b/peikarband/tools/scripts/diagnose-502.sh similarity index 100% rename from scripts/diagnose-502.sh rename to peikarband/tools/scripts/diagnose-502.sh diff --git a/scripts/update-env-json.sh b/peikarband/tools/scripts/update-env-json.sh similarity index 100% rename from scripts/update-env-json.sh rename to peikarband/tools/scripts/update-env-json.sh diff --git a/setup.py b/peikarband/tools/setup.py similarity index 100% rename from setup.py rename to peikarband/tools/setup.py diff --git a/restore-files.sh b/restore-files.sh new file mode 100755 index 0000000..53f7236 --- /dev/null +++ b/restore-files.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Script to restore original pipeline file names + +cd "$(dirname "$0")" + +echo "═══ Restoring original file names ═══" + +mv .woodpecker.yml .woodpecker-base.yml +mv .woodpecker-app.yml .woodpecker.yml + +echo "✓ Files restored:" +ls -lh .woodpecker*.yml + +echo "" +echo "Now you can:" +echo " 1. Commit the changes" +echo " 2. Push to trigger application pipeline" + diff --git a/src/presentation/web/assets/banner-3.gif b/src/presentation/web/assets/banner-3.gif deleted file mode 100644 index 93c2f3f..0000000 Binary files a/src/presentation/web/assets/banner-3.gif and /dev/null differ diff --git a/src/presentation/web/assets/custom.css b/src/presentation/web/assets/custom.css deleted file mode 100644 index 85bf92d..0000000 --- a/src/presentation/web/assets/custom.css +++ /dev/null @@ -1,227 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@100..900&display=swap'); - -body { - font-family: 'Vazirmatn', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -@keyframes gradientShift { - 0% { background-position: 0% 50%; } - 50% { background-position: 100% 50%; } - 100% { background-position: 0% 50%; } -} - -@keyframes glow { - 0% { box-shadow: 0 12px 40px rgba(27, 75, 127, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.2); } - 50% { box-shadow: 0 18px 50px rgba(27, 75, 127, 0.8), inset 0 1px 0 rgba(255, 255, 255, 0.3); } - 100% { box-shadow: 0 12px 40px rgba(27, 75, 127, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.2); } -} - -@keyframes pulse { - 0% { transform: scale(1); opacity: 1; } - 50% { transform: scale(1.05); opacity: 0.8; } - 100% { transform: scale(1); opacity: 1; } -} - -@keyframes float { - 0%, 100% { transform: translateY(0px); } - 50% { transform: translateY(-20px); } -} - -@keyframes floatSlow { - 0%, 100% { transform: translateY(0px) translateX(0px); } - 25% { transform: translateY(-15px) translateX(10px); } - 50% { transform: translateY(-30px) translateX(0px); } - 75% { transform: translateY(-15px) translateX(-10px); } -} - -@keyframes rotate { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } -} - -@keyframes scaleFloat { - 0%, 100% { transform: scale(1) translateY(0px); } - 50% { transform: scale(1.05) translateY(-15px); } -} - -@keyframes fadeInUp { - 0% { - opacity: 0; - transform: translateY(60px) scale(0.9); - } - 100% { - opacity: 1; - transform: translateY(0) scale(1); - } -} - -@keyframes fadeInScale { - 0% { - opacity: 0; - transform: scale(0.8); - } - 100% { - opacity: 1; - transform: scale(1); - } -} - -@keyframes slideInRight { - 0% { - opacity: 0; - transform: translateX(100px); - } - 100% { - opacity: 1; - transform: translateX(0); - } -} - -@keyframes floatComplex { - 0%, 100% { - transform: translateY(0px) translateX(0px) rotate(0deg); - } - 25% { - transform: translateY(-20px) translateX(15px) rotate(5deg); - } - 50% { - transform: translateY(-35px) translateX(5px) rotate(-3deg); - } - 75% { - transform: translateY(-18px) translateX(-12px) rotate(4deg); - } -} - -@keyframes rotateSubtle { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} - -@keyframes scaleBreath { - 0%, 100% { - transform: scale(1); - opacity: 0.7; - } - 50% { - transform: scale(1.1); - opacity: 0.9; - } -} - -@keyframes floatDiagonal { - 0%, 100% { - transform: translate(0, 0); - } - 50% { - transform: translate(-25px, -25px); - } -} - -@keyframes bobFloat { - 0%, 100% { - transform: translateY(0px) scale(1); - } - 50% { - transform: translateY(-25px) scale(1.05); - } -} - -/* Smooth scroll behavior */ -html { - scroll-behavior: smooth; -} - -/* Custom scrollbar */ -::-webkit-scrollbar { - width: 12px; -} - -::-webkit-scrollbar-track { - background: #0a1428; -} - -::-webkit-scrollbar-thumb { - background: linear-gradient(135deg, #1B4B7F, #4DB8C4); - border-radius: 6px; -} - -::-webkit-scrollbar-thumb:hover { - background: linear-gradient(135deg, #4DB8C4, #6DD7E5); -} - -/* Selection color */ -::selection { - background: rgba(77, 184, 196, 0.3); - color: #FFFFFF; -} - -::-moz-selection { - background: rgba(77, 184, 196, 0.3); - color: #FFFFFF; -} - -@keyframes fadeInRight { - 0% { - opacity: 0; - transform: translate3d(100%, 0, 0); - } - 100% { - opacity: 1; - transform: translate3d(0, 0, 0); - } -} - -@keyframes fadeInDown { - 0% { - opacity: 0; - transform: translate3d(0, -100%, 0); - } - 100% { - opacity: 1; - transform: translate3d(0, 0, 0); - } -} - -/* WordPress Section Floating Icons Animations */ -.wp-icon-1 { - animation: fadeInScale 1s ease-out 0.5s backwards, bobFloat 8s ease-in-out 2s infinite; -} - -.wp-icon-2 { - animation: fadeInScale 1s ease-out 1s backwards, floatDiagonal 9s ease-in-out 2.5s infinite; -} - -.wp-icon-3 { - animation: fadeInScale 1s ease-out 1.5s backwards, float 7s ease-in-out 3s infinite reverse; -} - -.wp-icon-4 { - animation: fadeInScale 1s ease-out 2s backwards, scaleBreath 9s ease-in-out 3.5s infinite; -} - -.wp-icon-5 { - animation: fadeInScale 1s ease-out 2.5s backwards, floatComplex 10s ease-in-out 4s infinite; -} - -.wp-icon-6 { - animation: fadeInScale 1s ease-out 3s backwards, rotateSubtle 40s linear 4s infinite, bobFloat 8s ease-in-out 4.5s infinite; -} - -.wp-card-1 { - animation: fadeInScale 1s ease-out 3.5s backwards, float 7s ease-in-out 5s infinite; -} - -.wp-card-2 { - animation: fadeInScale 1s ease-out 4s backwards, float 8s ease-in-out 5.5s infinite reverse; -} - -.wp-card-3 { - animation: fadeInScale 1s ease-out 4.5s backwards, float 6s ease-in-out 6s infinite; -} - diff --git a/src/presentation/web/assets/hero-servers.svg b/src/presentation/web/assets/hero-servers.svg deleted file mode 100644 index afc848e..0000000 --- a/src/presentation/web/assets/hero-servers.svg +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wired-flat-2579-logo-wordpress-hover-pinch.gif b/wired-flat-2579-logo-wordpress-hover-pinch.gif deleted file mode 100644 index e1141bd..0000000 Binary files a/wired-flat-2579-logo-wordpress-hover-pinch.gif and /dev/null differ diff --git a/woodpecker copy.yml b/woodpecker copy.yml deleted file mode 100644 index f90a106..0000000 --- a/woodpecker copy.yml +++ /dev/null @@ -1,439 +0,0 @@ -# Peikarband Platform - Woodpecker CI/CD Pipeline -# Complete production-ready pipeline with Harbor registry integration - -variables: - - &harbor_registry 'harbor.peikarband.ir' - - &image_name 'peikarband/landing' - - &python_version '3.11' - -# Global configuration -when: - - evaluate: 'CI_PIPELINE_EVENT != "cron"' - -# ============================================ -# STAGE 1: Code Quality & Linting -# ============================================ -steps: - lint-python: - image: python:${python_version}-slim - environment: - - PYTHONPATH=/woodpecker/src/workspace - commands: - - pip install --no-cache-dir flake8 black isort mypy - - echo "🔍 Running flake8..." - - flake8 src/ --max-line-length=120 --exclude=__pycache__,migrations --statistics - - echo "✅ Flake8 passed" - - echo "🔍 Running black check..." - - black --check src/ --line-length=120 - - echo "✅ Black check passed" - - echo "🔍 Running isort check..." - - isort --check-only src/ - - echo "✅ Isort check passed" - when: - branch: - include: - - main - - develop - - staging - - feature/* - - hotfix/* - - lint-yaml: - image: cytopia/yamllint:latest - commands: - - echo "🔍 Validating YAML files..." - - yamllint -c .yamllint.yml helm/ || true - - yamllint woodpecker.yml - - echo "✅ YAML validation completed" - when: - branch: - include: - - main - - develop - - staging - -# # ============================================ -# # STAGE 2: Unit Tests & Coverage -# # ============================================ -# test-unit: -# image: python:${python_version}-slim -# environment: -# - PYTHONPATH=/woodpecker/src/workspace -# - ENVIRONMENT=test -# - DATABASE_URL=postgresql://test:test@postgres:5432/test_db -# - REDIS_URL=redis://redis:6379/0 -# commands: -# - apt-get update && apt-get install -y --no-install-recommends postgresql-client -# - pip install --no-cache-dir -r requirements.txt -r requirements-dev.txt -# - echo "🧪 Running unit tests..." -# - pytest tests/unit/ -v --cov=src --cov-report=term --cov-report=xml --cov-report=html -# - echo "✅ Unit tests passed" -# - echo "📊 Coverage report generated" -# when: -# branch: -# include: -# - main -# - develop -# - staging -# - feature/* - -# test-integration: -# image: python:${python_version}-slim -# environment: -# - PYTHONPATH=/woodpecker/src/workspace -# - ENVIRONMENT=test -# - DATABASE_URL=postgresql://test:test@postgres:5432/test_db -# - REDIS_URL=redis://redis:6379/0 -# commands: -# - apt-get update && apt-get install -y --no-install-recommends postgresql-client -# - pip install --no-cache-dir -r requirements.txt -r requirements-dev.txt -# - echo "🧪 Running integration tests..." -# - pytest tests/integration/ -v --maxfail=3 -# - echo "✅ Integration tests passed" -# when: -# branch: -# include: -# - main -# - develop -# - staging - -# # ============================================ -# # STAGE 3: Security Scanning -# # ============================================ -# security-python-deps: -# image: python:${python_version}-slim -# commands: -# - pip install --no-cache-dir safety bandit -# - echo "🔒 Checking Python dependencies for vulnerabilities..." -# - safety check --json || true -# - echo "🔒 Running Bandit security linter..." -# - bandit -r src/ -f json -o bandit-report.json || true -# - echo "✅ Security scan completed" -# when: -# branch: -# include: -# - main -# - develop -# - staging - -# security-secrets: -# image: trufflesecurity/trufflehog:latest -# commands: -# - echo "🔐 Scanning for secrets and credentials..." -# - trufflehog filesystem . --json --no-update || true -# - echo "✅ Secret scan completed" -# when: -# branch: -# include: -# - main -# - develop -# - staging - -# ============================================ -# STAGE 4: Docker Build -# ============================================ - docker-build: - image: plugins/docker - settings: - registry: *harbor_registry - repo: ${harbor_registry}/${image_name} - tags: - - ${CI_COMMIT_SHA:0:8} - - ${CI_COMMIT_BRANCH} - - latest - username: - from_secret: harbor_username - password: - from_secret: harbor_password - build_args: - - ENVIRONMENT=production - - VERSION=${CI_COMMIT_SHA:0:8} - cache_from: - - ${harbor_registry}/${image_name}:latest - dockerfile: Dockerfile - dry_run: false - when: - branch: - include: - - main - - develop - - staging - event: - - push - - tag - -# # ============================================ -# # STAGE 5: Container Security Scan -# # ============================================ -# security-trivy: -# image: aquasec/trivy:latest -# commands: -# - echo "🔒 Scanning Docker image for vulnerabilities..." -# - trivy image -# --severity HIGH,CRITICAL -# --exit-code 0 -# --format json -# --output trivy-report.json -# ${harbor_registry}/${image_name}:${CI_COMMIT_SHA:0:8} -# - echo "✅ Trivy scan completed" -# - trivy image -# --severity HIGH,CRITICAL -# --format table -# ${harbor_registry}/${image_name}:${CI_COMMIT_SHA:0:8} -# when: -# branch: -# include: -# - main -# - develop -# - staging -# event: -# - push - -# ============================================ -# STAGE 6: Helm Validation -# ============================================ - helm-lint: - image: alpine/helm:latest - commands: - - echo "📦 Linting Helm chart..." - - helm lint helm/peikarband --strict - - echo "✅ Helm lint passed" - - echo "📦 Validating Helm template..." - - helm template peikarband helm/peikarband - --set image.repository=${harbor_registry}/${image_name} - --set image.tag=${CI_COMMIT_SHA:0:8} - --debug > /dev/null - - echo "✅ Helm template validation passed" - when: - branch: - include: - - main - - develop - - staging - -# ============================================ -# STAGE 7: Database Migration Check -# ============================================ - migration-check: - image: python:${python_version}-slim - environment: - - PYTHONPATH=/woodpecker/src/workspace - commands: - - pip install --no-cache-dir alembic sqlalchemy psycopg2-binary - - echo "🗄️ Checking database migrations..." - - alembic check || echo "⚠️ Migration check completed with warnings" - - alembic history - - echo "✅ Migration check completed" - when: - branch: - include: - - main - - develop - - staging - -# ============================================ -# STAGE 8: Deploy to Staging -# ============================================ - deploy-staging: - image: argoproj/argocd:latest - environment: - ARGOCD_SERVER: - from_secret: argocd_server - ARGOCD_AUTH_TOKEN: - from_secret: argocd_token - commands: - - echo "🚀 Deploying to Staging via ArgoCD..." - - argocd app set peikarband-staging - --helm-set image.tag=${CI_COMMIT_SHA:0:8} - - argocd app sync peikarband-staging --prune - - argocd app wait peikarband-staging --timeout 600 - - echo "✅ Staging deployment completed" - when: - branch: - - develop - - staging - event: - - push - -# ============================================ -# STAGE 9: Deploy to Production -# ============================================ - deploy-production: - image: argoproj/argocd:latest - environment: - ARGOCD_SERVER: - from_secret: argocd_server - ARGOCD_AUTH_TOKEN: - from_secret: argocd_token - commands: - - echo "🚀 Deploying to Production via ArgoCD..." - - argocd app set peikarband - --helm-set image.tag=${CI_COMMIT_SHA:0:8} - - argocd app sync peikarband --prune - - argocd app wait peikarband --timeout 600 - - echo "✅ Production deployment completed" - - echo "🎉 Version ${CI_COMMIT_SHA:0:8} is now live!" - when: - branch: - - main - event: - - push - - tag - -# ============================================ -# STAGE 10: Post-Deployment Verification -# ============================================ - verify-deployment: - image: curlimages/curl:latest - commands: - - echo "🔍 Verifying deployment..." - - sleep 30 - - | - if [ "${CI_COMMIT_BRANCH}" = "main" ]; then - ENDPOINT="https://peikarband.ir/ping" - else - ENDPOINT="https://staging.peikarband.ir/ping" - fi - - echo "Testing endpoint: $ENDPOINT" - - curl -f -s -o /dev/null -w "HTTP Status: %{http_code}\n" $ENDPOINT || echo "⚠️ Health check warning" - - echo "✅ Deployment verification completed" - when: - branch: - include: - - main - - develop - - staging - event: - - push - -# ============================================ -# STAGE 11: Notifications -# ============================================ - notify-telegram: - image: appleboy/drone-telegram:latest - settings: - token: - from_secret: telegram_bot_token - to: - from_secret: telegram_chat_id - format: markdown - message: > - {{#success build.status}} - ✅ **Build Success** - {{else}} - ❌ **Build Failed** - {{/success}} - - **Project:** Peikarband Landing - - **Branch:** ${CI_COMMIT_BRANCH} - - **Commit:** `${CI_COMMIT_SHA:0:8}` - - **Author:** ${CI_COMMIT_AUTHOR} - - **Message:** ${CI_COMMIT_MESSAGE} - - **Build:** [#${CI_BUILD_NUMBER}](${CI_BUILD_LINK}) - - **Duration:** ${CI_BUILD_FINISHED} - when: - status: - - success - - failure - branch: - - main - - develop - - staging - - notify-slack: - image: plugins/slack:latest - settings: - webhook: - from_secret: slack_webhook - channel: deployments - username: Woodpecker CI - template: > - {{#success build.status}} - :white_check_mark: Build #{{build.number}} succeeded - {{else}} - :x: Build #{{build.number}} failed - {{/success}} - - *Repository:* {{repo.name}} - *Branch:* {{build.branch}} - *Commit:* {{build.commit}} - *Author:* {{build.author}} - *Message:* {{build.message}} - *Link:* {{build.link}} - when: - status: - - success - - failure - branch: - - main - -# ============================================ -# Services (for testing) -# ============================================ -services: - postgres: - image: postgres:14-alpine - environment: - POSTGRES_USER: test - POSTGRES_PASSWORD: test - POSTGRES_DB: test_db - when: - branch: - include: - - main - - develop - - staging - - feature/* - - redis: - image: redis:7-alpine - when: - branch: - include: - - main - - develop - - staging - - feature/* - -# ============================================ -# Matrix Build (Optional - Multi-arch support) -# ============================================ -matrix: - include: - - PLATFORM: linux/amd64 - ENVIRONMENT: production - - PLATFORM: linux/arm64 - ENVIRONMENT: production - -# ============================================ -# Pipeline Configuration -# ============================================ -labels: - platform: linux/amd64 - backend: docker - -depends_on: [] - -skip_clone: false - -# Workspace configuration -workspace: - base: /woodpecker/src - path: workspace - -# Clone settings -clone: - git: - image: woodpeckerci/plugin-git:latest - settings: - depth: 50 - lfs: false - recursive: true - tags: true -