Модуль 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 впав
- Відкрий лог і знайди перший error. Не останній рядок, а перше повідомлення.
- Визнач крок: lint, test чи build. Це одразу звужує коло.
- Відтвори локально тією самою командою, що в пайплайні — з тими самими прапорцями.
- Якщо локально не відтворюється — шукай різницю середовищ: регістр файлів, версія Node, змінні оточення, часовий пояс.
- Виправ і зроби окремий коміт
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