Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Best practices: политики, код-ревью, оптимизация
best_practices

Best practices: политики, код-ревью, оптимизация

Политики ветвления, код-ревью процессы, бэкапы и аварийное восстановление, оптимизация производительности, масштабирование.

Best practices: политики, код-ревью, оптимизация

Политики ветвления, процессы код-ревью, бэкапы и аварийное восстановление, оптимизация производительности, масштабирование

#Мотивация

Вы внедрили Gitea, настроили аутентификацию, CI/CD и мониторинг. Но как обеспечить долгосрочную стабильность и эффективность платформы?

Проблемы без best practices:

  • Хаотичная структура веток → конфликты, потеря кода
  • Код-ревью «для галочки» → баги в production
  • Отсутствие бэкапов → риск потери всех данных
  • Деградация производительности → медленная работа через 6 месяцев

Эта тема — о проверенных практиках эксплуатации Gitea в production.

#Политики ветвления (Branching Policies)

#Git Flow для команды до 50 человек

main (production)
  ↑
  │ merge + release tag
develop (integration)
  ↑
  │ merge PR
feature/* (features)
  ↑
  │ commit
feature/login-page

Правила:

ВеткаНазначениеЗащитаMerge требования
mainProduction код✅ Protected2 approve, CI pass, no force push
developИнтеграция фич✅ Protected1 approve, CI pass
feature/*Разработка фич❌ Не защищена—
hotfix/*Срочные исправления⚠️ Частично1 approve, CI pass
release/*Подготовка релиза✅ Protected1 approve

#Настройка Branch Protection

Через веб-интерфейс:

  1. Репозиторий → Настройки → Branches
  2. Add Rule для main
  3. Параметры:
Branch name pattern: main

✅ Require pull request review before merging
   Minimum approvals: 2
   Dismiss stale reviews

✅ Require status checks to pass
   Contexts: ci/test, ci/build, ci/security-scan

✅ Include administrator

✅ Lock branch (запрет прямого push)

✅ Block merge if changes not reviewed

✅ Require signed commits (опционально)

Через API (массовая настройка):

#!/bin/bash GITEA_URL="http://git.company.ru" TOKEN="your_admin_token" # Список репозиториев REPOS=("backend/api" "frontend/web" "shared/lib") for repo in "${REPOS[@]}"; do curl -X POST "$GITEA_URL/api/v1/repos/$repo/branch_protections" \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "branch_name": "main", "enable_push_whitelist": true, "push_whitelist_usernames": ["admin", "tech-lead"], "enable_merge_whitelist": true, "merge_whitelist_usernames": ["admin", "tech-lead", "senior-dev"], "required_approvals": 2, "enable_status_check": true, "status_check_contexts": ["ci/test", "ci/build"], "block_on_official_review_requests": true, "block_on_rejected_reviews": true, "block_on_outdated_branch": true }' echo "✓ Настроена защита main для $repo" done

#Git Flow альтернативы

GitHub Flow (для continuous deployment):

main (always deployable)
  ↑
  │ PR + deploy preview
feature/*

Trunk-Based Development (для зрелых команд):

main (trunk)
  ↑
  │ short-lived feature branches (< 1 day)
  │ или feature flags
feature/*

#Процессы код-ревью

#Чеклист код-ревью

Для автора PR:

  • Код следует стилю проекта (lint проходит)
  • Все тесты проходят локально
  • Добавлены тесты для новой функциональности
  • Обновлена документация (README, комментарии)
  • Нет отладочного кода (console.log, debugger)
  • Commit messages осмысленные
  • PR описывает изменения и мотивацию

Для ревьювера:

  • Код решает поставленную задачу
  • Нет избыточной сложности
  • Обработаны edge cases и ошибки
  • Нет security issues (SQL injection, XSS)
  • Логи информативные (не содержат secrets)
  • Производительность не деградировала

#SLA на код-ревью

ПриоритетВремя первого ответаВремя merge
Critical (hotfix)30 минут2 часа
High (блокер спринта)4 часа1 день
Normal (стандартный)1 день3 дня
Low (улучшение)3 дня1 неделя

Автоматизация напоминаний:

# .gitea/workflows/review-reminder.yml name: Review Reminder on: pull_request: types: [opened, synchronize] jobs: remind: runs-on: ubuntu-latest steps: - name: Check PR age uses: actions/github-script@v7 with: script: | const pr = context.payload.pull_request; const now = new Date(); const created = new Date(pr.created_at); const hoursOld = (now - created) / 1000 / 60 / 60; if (hoursOld > 24) { // Напоминание в Slack/Telegram console.log(`PR #${pr.number} не ревьюирован ${Math.floor(hoursOld)} часов`); }

#Метрики код-ревью

МетрикаЦелевое значениеКак измерить
Time to First Review< 4 часовGitea API + скрипт
Time to Merge< 2 днейGitea API
Review Depth5-20 комментариев/PRGitea API
PR Size< 400 строкGitea API
Rework Rate< 30% PR требуют значительных правокАнализ итераций

Скрипт сбора метрик:

#!/bin/bash GITEA_URL="http://git.company.ru" TOKEN="your_token" ORG="myorg" # Получение всех PR за месяц curl -H "Authorization: token $TOKEN" \ "$GITEA_URL/api/v1/repos/$ORG/*/pulls?state=closed&updated_after=$(date -d '30 days ago' -I)" \ | jq -r '.[] | { number: .number, title: .title, created_at: .created_at, merged_at: .merged_at, additions: .additions, deletions: .deletions, comments: .comments }'

#Резервное копирование и восстановление

#Стратегия 3-2-1

3 копии данных
2 разных типа носителей
1 копия вне площадки

Для Gitea:

Копия 1: Production сервер (основная)
Копия 2: Локальный бэкап на NAS (ежедневный)
Копия 3: Офлайн бэкап в другом здании (еженедельный)

#Скрипт бэкапа production-ready

/opt/gitea/backup-production.sh:

#!/bin/bash set -euo pipefail # Конфигурация BACKUP_DIR="/opt/gitea/backups" RETENTION_DAYS=30 DATE=$(date +%Y%m%d_%H%M%S) HOSTNAME=$(hostname) LOG_FILE="/var/log/gitea-backup.log" # Функция логирования log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE" } # Проверка места на диске check_disk_space() { local available=$(df -B1 "$BACKUP_DIR" | awk 'NR==2 {print $4}') local required=$((5 * 1024 * 1024 * 1024)) # 5 GB минимум if [ "$available" -lt "$required" ]; then log "ERROR: Недостаточно места для бэкапа. Доступно: $((available / 1024 / 1024)) MB" exit 1 fi } # Создание бэкапа Gitea backup_gitea() { log "Начало бэкапа Gitea..." docker exec gitea gitea dump -F "$BACKUP_DIR/gitea-$DATE.zip" if [ -f "$BACKUP_DIR/gitea-$DATE.zip" ]; then local size=$(du -h "$BACKUP_DIR/gitea-$DATE.zip" | cut -f1) log "✓ Бэкап Gitea создан: $size" else log "ERROR: Не удалось создать бэкап Gitea" exit 1 fi } # Бэкап PostgreSQL backup_postgres() { log "Начало бэкапа PostgreSQL..." docker exec gitea-db pg_dump -U gitea gitea | \ gzip > "$BACKUP_DIR/postgres-$DATE.sql.gz" if [ -f "$BACKUP_DIR/postgres-$DATE.sql.gz" ]; then local size=$(du -h "$BACKUP_DIR/postgres-$DATE.sql.gz" | cut -f1) log "✓ Бэкап PostgreSQL создан: $size" else log "ERROR: Не удалось создать бэкап PostgreSQL" exit 1 fi } # Проверка целостности бэкапа verify_backup() { log "Проверка целостности бэкапов..." # Проверка ZIP архива if ! unzip -t "$BACKUP_DIR/gitea-$DATE.zip" > /dev/null 2>&1; then log "ERROR: Бэкап Gitea повреждён" exit 1 fi # Проверка SQL дампа if ! gzip -t "$BACKUP_DIR/postgres-$DATE.sql.gz" > /dev/null 2>&1; then log "ERROR: Бэкап PostgreSQL повреждён" exit 1 fi log "✓ Целостность бэкапов подтверждена" } # Очистка старых бэкапов cleanup_old() { log "Очистка бэкапов старше $RETENTION_DAYS дней..." find "$BACKUP_DIR" -name "gitea-*.zip" -mtime +$RETENTION_DAYS -delete find "$BACKUP_DIR" -name "postgres-*.sql.gz" -mtime +$RETENTION_DAYS -delete local count=$(find "$BACKUP_DIR" -name "*.zip" -o -name "*.sql.gz" | wc -l) log "✓ Осталось бэкапов: $count" } # Копирование на удалённый сервер (опционально) copy_offsite() { if [ -n "${OFFSITE_HOST:-}" ]; then log "Копирование на удалённый сервер..." rsync -avz \ "$BACKUP_DIR/gitea-$DATE.zip" \ "$BACKUP_DIR/postgres-$DATE.sql.gz" \ "$OFFSITE_HOST:/backups/gitea/" log "✓ Копирование завершено" fi } # Основная логика main() { log "=========================================" log "Запуск бэкапа Gitea ($DATE)" log "=========================================" check_disk_space backup_gitea backup_postgres verify_backup cleanup_old copy_offsite log "=========================================" log "Бэкап завершён успешно" log "=========================================" } main "$@"

#Восстановление из бэкапа

Сценарий 1: Восстановление после сбоя

#!/bin/bash set -euo pipefail BACKUP_FILE="/opt/gitea/backups/gitea-20260319_020000.zip" log "Начало восстановления из $BACKUP_FILE" # Остановка текущей Gitea docker compose down # Очистка данных rm -rf /opt/gitea/data/* # Восстановление docker exec gitea gitea restore --from "$BACKUP_FILE" # Запуск docker compose up -d log "Восстановление завершено"

Сценарий 2: Миграция на новый сервер

# На старом сервере scp /opt/gitea/backups/gitea-latest.zip user@new-server:/opt/gitea/ # На новом сервере docker compose up -d docker exec gitea gitea restore --from /opt/gitea/gitea-latest.zip

#Тестирование восстановления

Ежеквартальный drill:

  1. Выделить тестовый сервер
  2. Развернуть из последнего бэкапа
  3. Проверить:
    • Доступность веб-интерфейса
    • Вход пользователей (LDAP)
    • Доступность репозиториев
    • Работоспособность CI/CD
  4. Зафиксировать время восстановления (RTO)
  5. Сравнить с целевым RTO (< 4 часов)

#Оптимизация производительности

#Базовая настройка app.ini

[server] ; Отключение Gravatar (ускоряет загрузку) DISABLE_GRAVATAR = true ; Сжатие gzip ENABLE_GZIP = true ; Кэширование статики STATIC_CACHE_TIME = 86400 [cache] ; Redis для кэша ADAPTER = redis HOST = redis:6379 ITEM_TTL = 16h [session] ; Redis для сессий PROVIDER = redis PROVIDER_CONFIG = redis:6379 [database] ; Пул соединений MAX_IDLE_CONNS = 10 MAX_OPEN_CONNS = 100 ; Логирование медленных запросов LOG_SQL = true SLOW_QUERY_THRESHOLD = 1s [repository] ; Ограничение размера push MAX_PUSH_FILES = 100 ; Кэширование git GC_ARGS = --aggressive --auto [indexer] ; Elasticsearch для поиска ISSUE_INDEXER_TYPE = elasticsearch ISSUE_INDEXER_CONN_STR = http://elasticsearch:9200 REPO_INDEXER_ENABLED = true

#Мониторинг производительности

Ключевые метрики:

МетрикаНормаКритично
Response Time (p95)< 500ms> 2s
Database Query Time< 100ms> 1s
Git Clone Time (средний репо)< 5s> 30s
Memory Usage< 70%> 90%
Disk I/O Wait< 10%> 30%

Профилирование:

# Включение профайлера [server] PPROF_ENABLED = true PPROF_DATA_PATH = /data/pprof # Доступ к профайлеру curl http://git.company.ru:3000/debug/pprof/heap > heap.prof go tool pprof heap.prof

#Оптимизация PostgreSQL

-- Анализ медленных запросов SELECT query, calls, total_time, mean_time FROM pg_stat_statements ORDER BY mean_time DESC LIMIT 10; -- Индексы для частых запросов CREATE INDEX CONCURRENTLY idx_issue_repo ON issue(repo_id); CREATE INDEX CONCURRENTLY idx_comment_issue ON comment(issue_id); CREATE INDEX CONCURRENTLY idx_action_user ON action(user_id); -- Vacuum и analyze VACUUM ANALYZE;

#Масштабирование

#Вертикальное масштабирование

КомпонентМинимумMediumLarge
CPU2 cores4 cores8 cores
RAM4 GB8 GB16 GB
Disk50 GB SSD200 GB SSD500 GB NVMe
Пользователейдо 50до 200до 500

#Горизонтальное масштабирование

Архитектура HA:

                    ┌─────────────────┐
                    │  Load Balancer  │
                    │   (HAProxy/     │
                    │    NGINX)       │
                    └────────┬────────┘
                             │
              ┌──────────────┼──────────────┐
              │              │              │
       ┌──────▼──────┐ ┌─────▼─────┐ ┌──────▼──────┐
       │   Gitea 1   │ │  Gitea 2  │ │   Gitea 3   │
       │   :3000     │ │  :3000    │ │   :3000     │
       └──────┬──────┘ └─────┬─────┘ └──────┬──────┘
              │              │              │
              └──────────────┼──────────────┘
                             │
                    ┌────────▼────────┐
                    │   PostgreSQL    │
                    │   (репликация)  │
                    └────────┬────────┘
                             │
                    ┌────────▼────────┐
                    │   NFS / S3      │
                    │   (репозитории) │
                    └─────────────────┘

docker-compose для HA:

version: '3.8' services: gitea-1: image: gitea/gitea:latest environment: - GITEA__database__DB_TYPE=postgres - GITEA__database__HOST=postgres-primary:5432 volumes: - /shared/gitea-data:/data depends_on: - postgres-primary gitea-2: # same config gitea-3: # same config postgres-primary: image: bitnami/postgresql:15 environment: - POSTGRESQL_REPLICATION_MODE=master - POSTGRESQL_REPLICATION_USER=repl_user postgres-replica: image: bitnami/postgresql:15 environment: - POSTGRESQL_REPLICATION_MODE=slave - POSTGRESQL_MASTER_HOST=postgres-primary

#Чеклист production readiness

#Перед запуском

  • LDAP/SSO настроен и протестирован
  • 2FA включён для администраторов
  • HTTPS настроен с валидным сертификатом
  • Бэкапы настроены и протестированы
  • Мониторинг (Prometheus + Grafana) запущен
  • Алерты настроены (Telegram/Email)
  • Branch protection на main
  • CI/CD пайплайны работают
  • Документация для пользователей создана

#Еженедельно

  • Проверка логов на ошибки
  • Анализ метрик производительности
  • Проверка успешности бэкапов
  • Обзор открытых PR > 7 дней

#Ежемесячно

  • Обновление Gitea (security patches)
  • Тест восстановления из бэкапа
  • Аудит прав доступа
  • Review capacity planning

#Ежеквартально

  • Drill аварийного восстановления
  • Пересмотр политик безопасности
  • Обучение пользователей
  • Анализ метрик код-ревью