Кросс-платформенный package registry на доске выглядит безобидно: NuGet-пакеты лежат в одном месте, пайплайны тянут их из другого, все довольны. А потом токен протухает в самый неподходящий момент, три пайплайна ложатся на целый день — и команда на собственной шкуре узнаёт, какой невидимый налог она платила с каждого деплоя. Это история про тот день и про уборку, которая за ним последовала.

Пакеты в Azure, пайплайны в GitLab

Такую схему никто не проектирует специально — она нарастает сама. NuGet-пакеты жили в Azure DevOps. CI/CD крутился в GitLab. Между ними сидел personal access token, PAT, который тихо отсчитывал дни до своего протухания, и дату эту никто не выписал в календарь.

Каждый билд тянулся через эту щель. dotnet restore аутентифицировался в Azure по PAT, забирал пакеты и надеялся, что креды ещё живы. Почти всегда живы. Пока однажды не оказались мёртвыми. Токен протух посреди спринта, и три пайплайна разом покраснели, потому что все они опирались на один и тот же секрет. Целый день ушёл на то, что не дало ни одной фичи и ни одного фикса.

Zero trust, только не тот, который хороший

Хуже всего была культура, выросшая вокруг этой хрупкости. Никто ничему не доверял.

  • PAT-токены протухали посреди спринта — без предупреждения и без хозяина.
  • CI/CD-переменные были раскиданы по проектам без единой строчки документации.
  • Разработчики реально боялись трогать NuGet-конфиг: в прошлый раз кто-то его поправил — и три пайплайна легли на целый день.

Вот этот страх и есть настоящая цена. Когда люди перестают трогать систему из страха, что она рванёт, система перестаёт улучшаться. Она костенеет. Остаётся племенное знание о том, какой токен куда идёт, — и единственный человек, который в этом разбирался, уходит в отпуск ровно на той неделе, когда всё ломается.

Миграция: одна платформа для кода, пакетов и пайплайнов

Фикс был не гениальным. Он был структурным. Я перенёс всё в GitLab Package Registry — на ту же платформу, где уже жил код и крутились пайплайны. Те же стены, та же дверь.

Ключевой была аутентификация. Каждый personal access token заменили на CI_JOB_TOKEN. Он встроен в GitLab CI, ограничен рамками конкретного job'а и не требует никакой ротации. Отслеживать нечего: токен живёт ровно столько, сколько идёт job. Календарь ротации кредов и сюрпризы посреди спринта просто перестали быть классом проблем.

Кладбище переменных

Перенести пакеты — только половина работы. CI/CD-переменные были отдельным цирком, и вот их разбор как раз требовал головы.

Открыть список переменных было как открыть ящик со всяким хламом:

  • Старые Azure DevOps PAT, которые никто не помнил, когда создавал.
  • Дубли NuGet source URL с чуть-чуть разными именами — так что никогда не поймёшь, какой из них реально использует job.
  • Переменные, пережившие тех, кто их завёл.

Я проревизил каждую. По каждой вопрос был прямой: это вообще кто-нибудь ещё читает? Если нет — в топку. Если две делают одно и то же — в одну. Работа скучная, неблагодарная — и ровно такая, которую никто не делает, пока скука не превращается в аварию.

Как пайплайн выглядит теперь

Когда пакеты переехали в GitLab, а переменные вычистили, пайплайн схлопнулся в то, что объясняется на одном выдохе:

  • dotnet restore тянет из GitLab Package Registry.
  • Build и pack.
  • Push пакета обратно в тот же registry.

Каждый шаг аутентифицируется автоматически job-токеном. Никакого PAT в какой-то переменной. Никакого кросс-платформенного рукопожатия. Никакого напоминания в календаре «проротировать секрет, пока он не уронил три пайплайна в пятницу под вечер».

Вывод: не давайте пакетам и пайплайнам жить в разных мирах

Если ваши пакеты живут в одном мире, а пайплайны — в другом, вы платите налог с каждого деплоя. Он проявляется как оверхед на аутентификацию, как configuration drift, как племенное знание о том, какой кред куда идёт, — а время от времени как целый потерянный день, когда забытый токен наконец протухает.

Консолидируйте. Уберите код, пакеты и пайплайны за одну стену, чтобы платформа сама раздавала короткоживущие ограниченные креды, а не вы вручную нянчили долгоживущие. Один registry. Один поток аутентификации. Одной причиной меньше для пайплайна упасть в 17:00 в пятницу.

И честный вопрос напоследок: сколько токенов в ваших пайплайнах может протухнуть завтра — и знаете ли вы это на самом деле?