Angular IDPStrong Junior
Модулі / Процес: Git, PR, CI / CI і падіння збірки
🔥 0

Модуль 9 · урок 8 з 9

CI і падіння збірки

Останній пункт цілі: «inspect Azure Pipelines build logs to identify and resolve CI build or linting failures». Тобто від тебе не чекають, що ти писатимеш пайплайни — чекають, що ти вмітимеш прочитати лог і полагодити те, що впало.

Що робить пайплайн

# типова послідовність, однакова майже скрізь
npm ci                                                   # встановити залежності точно за lock-файлом
npx ng lint                                              # перевірити правила з модуля 2
npx ng test --watch=false --browsers=ChromeHeadless      # тести з модуля 8
npx ng build --configuration production                  # зібрати

Порядок не випадковий: спершу найдешевші перевірки. Лінтер падає за десять секунд, збірка йде хвилини — немає сенсу збирати те, що вже не проходить лінт.

Чому npm ci, а не npm install

ci ставить рівно те, що записано в package-lock.json, і падає, якщо lock розійшовся з package.json. install може мовчки оновити версії — і тоді збірка на машині розробника й у CI відрізняються. Класична ситуація «у мене працює» починається саме тут.

Як читати лог

Лог довгий, але правило одне: шукай перше слово «error», а не останнє. Після першої помилки решта — це зазвичай наслідки, які збивають з пантелику.

ПовідомленняЩо це насправді
error TS2322: Type 'string' is not assignable to type 'number'Помилка типів. Номер TS**** легко гуглиться
Unexpected any. Specify a different typeПравило no-explicit-any з модуля 2
Cannot find module './task.store'Часто різниця регістру в назві файлу: локально працює, у CI ні
1 timer(s) still in the queueТест із fakeAsync лишив незавершений таймер
Executed 12 of 40 (skipped 28)Забутий fit або fdescribe
bundle initial exceeded maximum budgetБандл переріс ліміт із angular.json
ChromeHeadless have not captured in 60000 msБраузер не піднявся — інфраструктурна проблема, не твій код
Різниця регістру — підступна

macOS і Windows не розрізняють Task.store.ts і task.store.ts, а Linux у CI розрізняє. Тому імпорт із помилкою в регістрі працює локально й падає в пайплайні. Якщо бачиш «Cannot find module» на файл, який точно існує — перевір великі й малі літери першим ділом.

Порядок дій, коли CI впав

  1. Відкрий лог і знайди перший error. Не останній рядок, а перше повідомлення.
  2. Визнач крок: lint, test чи build. Це одразу звужує коло.
  3. Відтвори локально тією самою командою, що в пайплайні — з тими самими прапорцями.
  4. Якщо локально не відтворюється — шукай різницю середовищ: регістр файлів, версія Node, змінні оточення, часовий пояс.
  5. Виправ і зроби окремий коміт fix(ci): … — щоб було видно причину.
# відтворити локально те саме, що робить CI
rm -rf node_modules
npm ci
npx ng lint
npx ng test --watch=false --browsers=ChromeHeadless
npx ng build --configuration production

Чого не робити

Правильно
  • Полагодити причину.
  • Якщо тест нестабільний — розібратись чому.
  • Попросити допомоги, якщо застряг більш ніж на годину.
  • Перезапустити пайплайн один раз, якщо схоже на збій інфраструктури.
Червоні прапорці
  • Вимкнути правило лінтера замість виправлення.
  • Позначити тест як xit, щоб не заважав.
  • Підняти ліміт бандла замість розбору, що його роздуло.
  • Перезапускати пайплайн уп'яте, сподіваючись, що пронесе.
Свій пайплайн у навчальному проєкті

GitHub Actions робиться одним файлом і дає ту саму практику: побачити червону галочку в PR, відкрити лог, знайти причину. Це ще й ловить помилки, які локально не помітно — той самий регістр файлів або залежність, забуту в package.json.

# .github/workflows/ci.yml
name: CI
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npx ng lint
      - run: npx ng test --watch=false --browsers=ChromeHeadless
      - run: npx ng build --configuration production