# Release Lifecycle Management

Управление жизненным циклом релизов дистрибутивов (добавление новых, удаление старых).

## Обзор

Дистрибутивы Linux имеют жизненный цикл:
- **Новые релизы**: Debian Trixie (13), Ubuntu Oracular (24.10)
- **Поддерживаемые**: Debian Bookworm (12), Ubuntu Noble (24.04)
- **Устаревшие**: Debian Bullseye (11 - EOL), Ubuntu Jammy (22.04 - скоро EOL)

debrepomanager автоматически поддерживает любые codenames - нужно только создать первый репозиторий.

## Добавление нового релиза

### Когда добавлять
- Вышла новая версия дистрибутива (Debian Trixie, Ubuntu Oracular)
- Нужно начать поддержку новой платформы
- Тестирование на новом релизе

### Процесс добавления

#### 1. Создать первый репозиторий для нового codename

```bash
# Вариант 1: Создать пустой репозиторий явно
debrepomanager create-repo trixie jethome-tools

# Вариант 2: Добавить пакеты (auto_create создаст репозиторий)
debrepomanager add --codename trixie --component jethome-tools --packages ./packages/*.deb

# Вариант 3: Через repoadd
./scripts/repoadd stable trixie ./packages/ jethome-tools
```

#### 2. Создать все необходимые компоненты

```bash
# Основные компоненты для нового релиза
debrepomanager create-repo trixie jethome-tools
debrepomanager create-repo trixie jethome-trixie      # BSP для нового релиза
debrepomanager create-repo trixie jethome-armbian     # Если используется

# Или через repoadd
for component in jethome-tools jethome-trixie jethome-armbian; do
    ./scripts/repoadd stable trixie ./packages-${component}/ ${component}
done
```

#### 3. Обновить nginx конфигурацию

Добавьте новый codename в pool location:

```nginx
location ~ ^/pool/(.*)$ {
    # Добавить trixie в начало списка (новые релизы приоритетнее)
    try_files $uri /trixie/$uri /bookworm/$uri /noble/$uri /jammy/$uri =404;
}
```

Перезапустите nginx:
```bash
sudo nginx -t
sudo systemctl reload nginx
```

#### 4. Создать симлинки для старого формата

```bash
# Создать симлинки для всех компонентов нового релиза
debrepomanager fix-symlinks --codename trixie

# Проверить результат
debrepomanager fix-symlinks --codename trixie --check-only
```

#### 5. Проверить работу

```bash
# Проверить новый формат
curl -I http://repo.site.com/trixie/jethome-tools/dists/jethome-tools/Release

# Проверить старый формат (через nginx rewrite)
curl -I http://repo.site.com/dists/trixie/jethome-tools/Release

# Тест с APT
echo "deb http://repo.site.com/trixie jethome-tools main" | \
    sudo tee /etc/apt/sources.list.d/jethome-trixie.list
sudo apt update
```

#### 6. Документировать в README

Обновите документацию клиентов:
```markdown
## Debian 13 (Trixie)

# /etc/apt/sources.list.d/jethome.list
deb http://repo.site.com/trixie jethome-tools main
deb http://repo.site.com/trixie jethome-trixie main
```

### Автоматизация

Скрипт для быстрого добавления нового релиза:

```bash
#!/bin/bash
# add-new-release.sh

CODENAME=$1
COMPONENTS=("jethome-tools" "jethome-${CODENAME}" "jethome-armbian")

if [ -z "$CODENAME" ]; then
    echo "Usage: $0 <codename>"
    echo "Example: $0 trixie"
    exit 1
fi

echo "Adding new release: $CODENAME"

# Создать компоненты
for component in "${COMPONENTS[@]}"; do
    echo "Creating $CODENAME/$component..."
    debrepomanager create-repo "$CODENAME" "$component"
done

echo "✓ Repositories created"

# Создать симлинки
echo "Creating dual format symlinks..."
debrepomanager fix-symlinks --codename "$CODENAME"

echo "✓ Symlinks created"

# Показать список
echo ""
echo "Created repositories:"
debrepomanager list --codename "$CODENAME"

echo ""
echo "Next steps:"
echo "  1. Update nginx config pool location (add /${CODENAME}/)"
echo "  2. Reload nginx: sudo systemctl reload nginx"
echo "  3. Add packages: ./scripts/repoadd stable $CODENAME <dir> <component>"
echo "  4. Update client documentation"
```

## Удаление устаревшего релиза

### Когда удалять
- Релиз достиг End of Life (EOL)
- Нет активных пользователей на старом релизе
- Нужно освободить место на диске

### Процесс удаления

#### 1. Проверить активность

Перед удалением проверьте, используется ли релиз:

```bash
# Проверить nginx логи
sudo grep "/bullseye/" /var/log/nginx/repo-access.log | \
    grep -E "$(date +%d/%b/%Y)" | wc -l

# Проверить последние запросы
sudo grep "/bullseye/" /var/log/nginx/repo-access.log | tail -20

# Статистика за месяц
sudo grep "/bullseye/" /var/log/nginx/repo-access.log.* | wc -l
```

#### 2. Уведомить пользователей

Перед удалением уведомите пользователей (email, announcement):

```
Debian Bullseye (11) EOL Notice

Debian Bullseye has reached End of Life.
Repository support will end on 2025-12-31.

Action required:
  - Upgrade to Debian Bookworm (12) or newer
  - Update APT sources before 2025-12-31

New repository format:
  deb http://repo.site.com/bookworm jethome-tools main
```

#### 3. Список репозиториев для удаления

```bash
# Показать все репозитории для codename
debrepomanager list --codename bullseye

# Пример вывода:
# bullseye/jethome-tools
# bullseye/jethome-bullseye
# bullseye/jethome-armbian
```

#### 4. Удалить репозитории

**Опция A: По одному (с подтверждением)**
```bash
# Удаление с подтверждением
debrepomanager delete-repo bullseye jethome-tools
debrepomanager delete-repo bullseye jethome-bullseye
debrepomanager delete-repo bullseye jethome-armbian
```

**Опция B: Скрипт для всех компонентов**
```bash
#!/bin/bash
# remove-release.sh

CODENAME=$1

if [ -z "$CODENAME" ]; then
    echo "Usage: $0 <codename>"
    echo "Example: $0 bullseye"
    exit 1
fi

echo "WARNING: This will DELETE all repositories for $CODENAME"
read -p "Are you sure? Type '$CODENAME' to confirm: " confirm

if [ "$confirm" != "$CODENAME" ]; then
    echo "Aborted"
    exit 1
fi

# Получить список компонентов
components=$(debrepomanager list --codename "$CODENAME" | grep "^$CODENAME/" | cut -d'/' -f2)

if [ -z "$components" ]; then
    echo "No repositories found for $CODENAME"
    exit 0
fi

echo "Found components:"
echo "$components"
echo ""

# Удалить каждый репозиторий
for component in $components; do
    echo "Deleting $CODENAME/$component..."
    debrepomanager delete-repo "$CODENAME" "$component" --yes
done

echo "✓ All repositories for $CODENAME deleted"
```

#### 5. Очистить aptly root

```bash
# Удалить весь aptly root для codename (освобождает место)
sudo rm -rf /srv/aptly/$CODENAME/

# Или сохранить для архива
sudo mv /srv/aptly/$CODENAME/ /srv/aptly/archive/$CODENAME-$(date +%Y%m%d)
```

#### 6. Очистить publish директорию

```bash
# Удалить опубликованные файлы
sudo rm -rf /opt/repo/public/$CODENAME/

# Удалить симлинки
sudo rm -rf /opt/repo/public/dists/$CODENAME/

# Или архивировать
sudo tar czf /backup/repo-$CODENAME-$(date +%Y%m%d).tar.gz \
    /opt/repo/public/$CODENAME/ \
    /opt/repo/public/dists/$CODENAME/
sudo rm -rf /opt/repo/public/$CODENAME/
sudo rm -rf /opt/repo/public/dists/$CODENAME/
```

#### 7. Обновить nginx конфигурацию

Удалите устаревший codename из pool location:

```nginx
location ~ ^/pool/(.*)$ {
    # Удалить bullseye из списка
    try_files $uri /trixie/$uri /bookworm/$uri /noble/$uri =404;
}
```

Перезапустите nginx:
```bash
sudo nginx -t
sudo systemctl reload nginx
```

#### 8. Обновить документацию

Удалите примеры для устаревшего релиза из:
- README.md
- APT_CONFIGURATION.md
- Client setup guides

Добавьте в changelog:
```markdown
## [Version] - Date

### Removed
- Debian Bullseye (11) support - reached EOL
  - Repository removed: bullseye/*
  - Use Debian Bookworm (12) or newer
```

## Примеры жизненного цикла

### Сценарий 1: Debian 13 (Trixie) released

```bash
# 1. Создать репозитории
debrepomanager create-repo trixie jethome-tools
debrepomanager create-repo trixie jethome-trixie
debrepomanager create-repo trixie jethome-armbian

# 2. Загрузить пакеты
./scripts/repoadd stable trixie ./packages-tools/ jethome-tools
./scripts/repoadd stable trixie ./packages-bsp/ jethome-trixie

# 3. Создать симлинки
debrepomanager fix-symlinks --codename trixie

# 4. Обновить nginx (добавить trixie в pool)
sudo nano /etc/nginx/sites-available/debian-repo
sudo systemctl reload nginx

# 5. Анонсировать клиентам
# Отправить email с новым sources.list
```

### Сценарий 2: Debian 11 (Bullseye) EOL

```bash
# 1. Проверить использование
sudo grep "/bullseye/" /var/log/nginx/repo-access.log.* | wc -l

# 2. Если активности нет > 30 дней - удалять

# 3. Архивировать (опционально)
sudo tar czf /backup/bullseye-$(date +%Y%m%d).tar.gz \
    /opt/repo/public/bullseye/ \
    /srv/aptly/bullseye/

# 4. Удалить все репозитории
for comp in $(debrepomanager list --codename bullseye | cut -d'/' -f2); do
    debrepomanager delete-repo bullseye $comp --yes
done

# 5. Очистить файлы
sudo rm -rf /srv/aptly/bullseye/
sudo rm -rf /opt/repo/public/bullseye/
sudo rm -rf /opt/repo/public/dists/bullseye/

# 6. Обновить nginx (удалить bullseye из pool)
sudo nano /etc/nginx/sites-available/debian-repo
sudo systemctl reload nginx

# 7. Обновить документацию
```

### Сценарий 3: Миграция пользователей Bullseye → Bookworm

```bash
# 1. Создать announcement
cat > /opt/repo/public/BULLSEYE_EOL.txt <<EOF
NOTICE: Debian Bullseye (11) EOL

Debian Bullseye has reached End of Life on 2024-08-31.
This repository will stop supporting bullseye on 2025-12-31.

Migration Instructions:
  1. Upgrade to Debian Bookworm (12):
     sudo apt update && sudo apt full-upgrade

  2. Update repository sources:
     # Old (bullseye)
     deb http://repo.site.com/bullseye jethome-tools main

     # New (bookworm)
     deb http://repo.site.com/bookworm jethome-tools main

  3. Update and upgrade:
     sudo apt update
     sudo apt upgrade

Support: support@site.com
EOF

# 2. Показать notice через nginx
location = /BULLSEYE_EOL {
    alias /opt/repo/public/BULLSEYE_EOL.txt;
    default_type text/plain;
}

# 3. Отправить email пользователям

# 4. Grace period: 3-6 месяцев

# 5. После grace period - удалить (см. выше)
```

## CLI Commands

### Создать новый релиз

```bash
# Создать репозиторий
debrepomanager create-repo <codename> <component> [--architectures amd64,arm64]

# Примеры
debrepomanager create-repo trixie jethome-tools
debrepomanager create-repo oracular jethome-noble --architectures amd64,arm64,riscv64
```

### Удалить старый релиз

```bash
# Удалить один компонент
debrepomanager delete-repo <codename> <component>

# С авто-подтверждением (для скриптов)
debrepomanager delete-repo bullseye jethome-tools --yes

# Примеры
debrepomanager delete-repo bullseye jethome-tools
debrepomanager delete-repo jammy jethome-armbian --yes
```

### Проверить что существует

```bash
# Список всех репозиториев
debrepomanager list

# Репозитории конкретного codename
debrepomanager list --codename bullseye

# Пакеты в конкретном компоненте
debrepomanager list --codename bullseye --component jethome-tools
```

## Автоматизация

### Скрипт: Добавить новый релиз

```bash
#!/bin/bash
# scripts/add-release.sh

CODENAME=$1
COMPONENTS=${2:-"jethome-tools jethome-${CODENAME} jethome-armbian"}

if [ -z "$CODENAME" ]; then
    echo "Usage: $0 <codename> [components]"
    echo "Example: $0 trixie"
    echo "         $0 trixie 'jethome-tools jethome-trixie'"
    exit 1
fi

echo "=== Adding new release: $CODENAME ==="
echo "Components: $COMPONENTS"
echo ""

# Создать репозитории
for component in $COMPONENTS; do
    echo "→ Creating $CODENAME/$component..."
    debrepomanager create-repo "$CODENAME" "$component" || {
        echo "✗ Failed to create $CODENAME/$component"
        exit 1
    }
    echo "✓ Created $CODENAME/$component"
done

# Создать симлинки
echo ""
echo "→ Creating dual format symlinks..."
debrepomanager fix-symlinks --codename "$CODENAME"
echo "✓ Symlinks created"

# Проверить
echo ""
echo "→ Verifying repositories..."
debrepomanager list --codename "$CODENAME"

echo ""
echo "=== $CODENAME added successfully ==="
echo ""
echo "Next steps:"
echo "  1. Add packages:"
echo "     ./scripts/repoadd stable $CODENAME <dir> <component>"
echo ""
echo "  2. Update nginx config:"
echo "     location ~ ^/pool/(.*)$ {"
echo "         try_files \$uri /$CODENAME/\$uri /bookworm/\$uri ... =404;"
echo "     }"
echo ""
echo "  3. Reload nginx:"
echo "     sudo systemctl reload nginx"
echo ""
echo "  4. Update client documentation"
```

### Скрипт: Удалить старый релиз

```bash
#!/bin/bash
# scripts/remove-release.sh

CODENAME=$1
BACKUP=${2:-yes}  # yes/no

if [ -z "$CODENAME" ]; then
    echo "Usage: $0 <codename> [backup]"
    echo "Example: $0 bullseye yes"
    exit 1
fi

echo "=== Removing release: $CODENAME ==="
echo ""

# Проверка активности
echo "→ Checking activity..."
activity=$(sudo grep "/$CODENAME/" /var/log/nginx/repo-access.log* 2>/dev/null | wc -l || echo "0")
echo "  Activity in logs: $activity requests"

if [ "$activity" -gt 100 ]; then
    echo "⚠️  WARNING: Codename $CODENAME has $activity requests in logs"
    read -p "Continue anyway? (yes/no): " confirm
    [ "$confirm" = "yes" ] || exit 1
fi

# Список репозиториев
echo ""
echo "→ Repositories to delete:"
debrepomanager list --codename "$CODENAME"
echo ""

# Подтверждение
read -p "Type '$CODENAME' to confirm deletion: " confirm
if [ "$confirm" != "$CODENAME" ]; then
    echo "Aborted"
    exit 1
fi

# Создать backup
if [ "$BACKUP" = "yes" ]; then
    BACKUP_FILE="/backup/repo-${CODENAME}-$(date +%Y%m%d_%H%M%S).tar.gz"
    echo ""
    echo "→ Creating backup: $BACKUP_FILE"
    sudo mkdir -p /backup
    sudo tar czf "$BACKUP_FILE" \
        /opt/repo/public/$CODENAME/ \
        /opt/repo/public/dists/$CODENAME/ \
        /srv/aptly/$CODENAME/ \
        2>/dev/null || echo "⚠️  Some paths not found (ok if already removed)"
    echo "✓ Backup created: $BACKUP_FILE"
fi

# Удалить репозитории через debrepomanager
echo ""
echo "→ Deleting repositories..."
components=$(debrepomanager list --codename "$CODENAME" 2>/dev/null | grep "^$CODENAME/" | cut -d'/' -f2 || echo "")

if [ -n "$components" ]; then
    for component in $components; do
        echo "  Deleting $CODENAME/$component..."
        debrepomanager delete-repo "$CODENAME" "$component" --yes 2>&1 || \
            echo "  ⚠️  Failed to delete $CODENAME/$component (may not exist)"
    done
else
    echo "  No repositories found via debrepomanager"
fi

# Очистить файлы вручную (на случай если debrepomanager не удалил)
echo ""
echo "→ Cleaning up files..."
sudo rm -rf /srv/aptly/$CODENAME/ && echo "✓ Removed /srv/aptly/$CODENAME/"
sudo rm -rf /opt/repo/public/$CODENAME/ && echo "✓ Removed /opt/repo/public/$CODENAME/"
sudo rm -rf /opt/repo/public/dists/$CODENAME/ && echo "✓ Removed /opt/repo/public/dists/$CODENAME/"

echo ""
echo "=== $CODENAME removed successfully ==="
echo ""
echo "Next steps:"
echo "  1. Update nginx config (remove /$CODENAME/ from pool location)"
echo "  2. Reload nginx: sudo systemctl reload nginx"
echo "  3. Update client documentation"
echo "  4. Send notification to users"
if [ "$BACKUP" = "yes" ]; then
    echo "  5. Backup saved to: $BACKUP_FILE"
fi
```

## Best Practices

### Планирование

**График поддержки релизов:**
- **Поддерживаем**: Current stable + 1-2 предыдущих
- **Пример**: Trixie (13) + Bookworm (12) + Bullseye (11, до EOL)

**Timeline добавления нового релиза:**
1. **Beta**: За 3-6 месяцев до официального релиза
2. **Stable**: После официального релиза
3. **Production**: После тестирования (1-2 недели)

**Timeline удаления старого релиза:**
1. **EOL Announcement**: За 6 месяцев до удаления
2. **Grace Period**: 3-6 месяцев после EOL
3. **Removal**: После grace period + проверка активности

### Коммуникация

**Уведомления пользователям:**
- Email newsletter за 3 месяца
- Email reminder за 1 месяц
- Website announcement
- MOTD в пакетах (если возможно)

### Архивирование

**Что сохранять:**
- Последний snapshot каждого компонента
- Metadata и конфигурация
- Статистика использования

**Где хранить:**
```bash
/backup/archive/
├── bullseye-20250131.tar.gz
├── jammy-20250601.tar.gz
└── focal-20240315.tar.gz
```

**Retention policy:**
- Сохранять backup 1 год после удаления
- Или до полного прекращения запросов

## Мониторинг

### Отслеживание активности по релизам

```bash
# Активность за последний месяц
for codename in bullseye bookworm trixie; do
    count=$(sudo grep "/$codename/" /var/log/nginx/repo-access.log* 2>/dev/null | wc -l)
    echo "$codename: $count requests"
done

# Топ пакетов по релизам
sudo awk '{print $7}' /var/log/nginx/repo-access.log | \
    grep "\.deb$" | \
    sed -E 's|/([^/]+)/.*|\1|' | \
    sort | uniq -c | sort -rn
```

### Dashboard (опционально)

Создайте простой мониторинг:

```bash
#!/bin/bash
# dashboard.sh

echo "Repository Dashboard"
echo "===================="
echo ""

for codename in bullseye bookworm trixie noble; do
    repos=$(debrepomanager list --codename $codename 2>/dev/null | wc -l)
    activity=$(sudo grep "/$codename/" /var/log/nginx/repo-access.log* 2>/dev/null | wc -l || echo "0")
    packages=$(find /opt/repo/public/$codename/pool -name "*.deb" 2>/dev/null | wc -l)

    printf "%-12s Repos: %2d  Packages: %4d  Activity: %5d\n" \
        "$codename:" "$repos" "$packages" "$activity"
done
```

## Troubleshooting

### Репозиторий не удаляется

```bash
# Проверить зависимости (snapshots)
cd /srv/aptly/$CODENAME
aptly -config=aptly.conf snapshot list

# Удалить snapshots вручную
aptly -config=aptly.conf snapshot drop snapshot-name

# Попробовать удалить снова
debrepomanager delete-repo $CODENAME $COMPONENT --yes
```

### Файлы остались после удаления

```bash
# Найти оставшиеся файлы
find /opt/repo/public -name "*$CODENAME*" -type f,d

# Очистить вручную
sudo rm -rf /opt/repo/public/$CODENAME
sudo rm -rf /opt/repo/public/dists/$CODENAME
```

### Пользователи всё ещё обращаются к удалённому релизу

```bash
# Создать redirect в nginx
location ~ ^/$REMOVED_CODENAME/ {
    return 410 "This release is no longer supported. Please upgrade to bookworm or newer.";
    add_header Content-Type text/plain;
}

# Или 301 redirect на новый релиз
location ~ ^/bullseye/(.*)$ {
    return 301 /bookworm/$1;
}
```

## См. также

- [ARCHITECTURE.md](ARCHITECTURE.md) - Multi-codename architecture
- [DEPLOYMENT_GUIDE.md](DEPLOYMENT_GUIDE.md) - Deployment procedures
- [NGINX_MULTI_ENV.md](NGINX_MULTI_ENV.md) - Nginx configuration
- [REPOADD_SCRIPT.md](REPOADD_SCRIPT.md) - Package upload script

