Continuous Integration (CI) — јесте пракса развоја у којој сваки члан тима интегрише своје промене у заједнички репозиторијум најмање једном дневно, а свака интеграција се проверава аутоматском компилацијом и тестовима. CI открива конфликте кода и регресијске грешке у раним фазама, смањујући трошкове њиховог исправљања. Према Puppet State of DevOps Report, 2025, тимови са CI поправљају грешке 4 пута брже од тимова без аутоматизације.
Главне тачке
Continuous Integration (CI) — јесте методологија развоја која аутоматизује процес интеграције кода од више учесника у јединствену базу кода. Термин је увео Мартин Фаулер почетком 2000-их као скуп пракси које спречавају „пакао интеграције“ — ситуацију у којој програмери раде изоловано недељама, а при спајању промена настају бројни конфликти који захтевају дане ручног решавања.
Без CI, програмер завршава функцију, покушава да споји своје промене са main граном и открива да су колеге измениле исте датотеке. Решавање конфликата траје сатима и често ломи радни код. CI решава овај проблем принудном интеграцијом неколико пута дневно: што је интеграција чешћа, мање је конфликата и лакше је њихово решавање. Пракса показује да при дневној интеграцији решавање конфликта траје минуте, а при недељној — сате.
Према IBM Systems Sciences Institute, трошак исправљања грешке у фази писања кода износи $25, у фази тестирања — $100, у фази продукције — $2 500. CI помера откривање дефеката максимално улево (shift left), откривајући грешке у фази комита, када је њихово исправљање практично бесплатно. Тимови са CI проводе у просеку 15% времена на отклањање грешака наспрам 35% код тимова без CI.
Мартин Фаулер је дефинисао кључне праксе CI које остају актуелне без обзира на технолошки стек. Поштовање ових принципа гарантује да CI доноси користи, а не постаје бирократско оптерећење. Мобилни развој намеће додатне захтеве, али језгро остаје непромењено.
Цео код пројекта чува се у једном репозиторијуму са јединственим системом контроле верзија (Git). Јединствени извор истине искључује ситуацију у којој се функција развија у форку и не синхронизује се са главном базом кода недељама. У мобилним пројектима, то значи да Android, iOS и backend делови могу бити у једном репозиторијуму (монорепозиторијум) или у одвојеним репозиторијумима са заједничком шемом верзионисања.
Компилација пројекта мора се извршити једном командом. За Android је то ./gradlew assembleDebug, за iOS — xcodebuild или fastlane build. Скрипт компилације проверава репродуцибилност: компилација на CI серверу мора дати исти резултат као на машини програмера. Све разлике у окружењу отклањају се контејнеризацијом или IaC (Infrastructure as Code).
Након компилације извршавају се сви нивои тестова: модуларни, интеграциони и UI. Ако тестови падну — комит се сматра неважећим. Одржавање зеленог статуса је заједничка одговорност тима. У мобилним пројектима често се раздвајају брзи тестови (извршавају се до 5 минута на сваки комит) и спори тестови (UI тестови на правим уређајима, покрећу се ређе).
// Пример јединичног теста са CI-friendly извештајем
class LoginViewModelTest {
private val repository = mock<AuthRepository>()
private val viewModel = LoginViewModel(repository)
@Test
fun loginWithValidCredentials_success() {
val email = "test@example.com"
val password = "ValidPass123"
whenever(repository.login(email, password))
.thenReturn(Result.success(User("token-xyz")))
val result = viewModel.login(email, password)
assertEquals(LoginState.Success, result)
verify(repository).login(email, password)
}
}
Резултати CI су јавни за цео тим: сви виде чији је комит сломио компилацију. Транспарентност ствара културу одговорности: програмери проверавају своје промене пре push-а и поправљају сломљену компилацију ван реда. CI сервер шаље обавештења у Slack или Telegram при промени статуса компилације.
Потпуни CI систем састоји се од неколико компоненти које међусобно делују. Свака компонента је одговорна за свој део цевовода: од покретања до извештаја. Разумевање архитектуре CI помаже у дијагностици проблема и оптимизацији перформанси.
Централна компонента која управља редом компилација, дистрибуцијом ресурса и објављивањем резултата. CI сервер може бити облачни (GitHub Actions, GitLab CI, CircleCI) или self-hosted (Jenkins, TeamCity). Сервер прати промене у репозиторијуму путем webhook-а или polling-а и покреће pipeline при сваком push-у или pull request-у.
Ранери — су виртуелне или физичке машине које извршавају задатке компилације. У облачним CI-евима, ранери се обезбеђују од стране провајдера и плаћају се према времену коришћења. Self-hosted ранери се инсталирају на сопственој инфраструктури и захтевају одржавање. За iOS компилације потребни су macOS ранери, за Android — Linux или Windows.
Након компилације, CI систем чува артефакте (APK, IPA, извештаје тестова) у складишту — доступни су за преузимање и примену. Кеширање зависности (Gradle cache, CocoaPods cache) између покретања убрзава наредне компилације 3–5 пута.
| Компонента | Намена | Пример |
|---|---|---|
| CI сервер | Оркестрација компилација | Jenkins, GitHub Actions |
| Ранер | Извршавање задатака | macOS ранер за iOS |
| Репозиторијум | Чување кода | GitHub, GitLab |
| Artifact storage | Чување артефаката | AWS S3, Artifactory |
| Notification | Обавештавање тима | Slack, Telegram, email |
Мобилни развој поставља посебне захтеве за CI, различите од web или backend пројеката. Дуга компилација (3–15 минута за Android, 5–20 минута за iOS), више типова артефаката (APK, AAB, IPA), потреба за потписивањем и обфускацијом — све то захтева индивидуално подешавање CI pipeline-а.
Типичан CI за Android укључује: линтинг (ktlint, detekt) и статичку анализу, јединичне тестове са JUnit и MockK, компилацију debug и release APK/AAB, инструменталне тестове на емулатору унутар CI и објављивање артефаката. Gradle кеш убрзава поновне компилације — без њега свака компилација поново преузима зависности, губећи 3–5 минута.
iOS CI захтева macOS ранер за компилацију Swift/Objective-C кода. Pipeline укључује: инсталацију CocoaPods или SPM зависности, SwiftLint за проверу стила, јединичне тестове са XCTest, компилацију IPA, потписивање сертификатима путем Fastlane match и отпремање у TestFlight. Self-hosted ранер на Mac mini или Mac-у у центру података — алтернатива облачним macOS ранерима.
Flutter и React Native се компилирају у native билдове за обе платформе. CI мора да подржава два ранера: Linux за Android компилацију и macOS за iOS компилацију. Оптимална стратегија — одвојени pipeline: Android компилација на Linux ранеру, iOS компилација на macOS ранеру, након чега се оба артефакта спајају у један release.
Избор CI алата зависи од величине тима, потребних перформанси, буџета и технолошког стека. Испод је поређење популарних решења са акцентом на мобилни развој. Self-hosted решења дају контролу, али захтевају администрирање, облачна — удобност, али ограничавају конфигурацију.
Бесплатан за јавне репозиторијуме (2000 минута/месечно). GitHub Actions нуди екосистем готових акција за Android (gradle/actions) и iOS (apple-actions). Минус — macOS ранери доступни само на плаћеним тарифама. Идеалан за Open Source и мале тимове који већ користе GitHub.
Self-hosted CI сервер са отвореним изворним кодом. Jenkins се подешава путем Groovy Pipeline-а, подржава стотине додатака и ради на било ком хардверу. Захтева DevOps инжењера за инсталацију и одржавање. Популаран у enterprise сегменту где је контрола над инфраструктуром критична.
Уграђени CI/CD у GitLab-у са отвореном ранер архитектуром. GitLab CI омогућава коришћење сопствених ранера (укључујући macOS) на бесплатној тарифи. YAML конфигурација је моћнија од GitHub Actions, али тежа за савладавање. Погодан за тимове који користе GitLab као јединствену DevOps платформу.
Облачни CI са акцентом на брзину. CircleCI подржава Docker, macOS и Android слике, аутоматски кешира зависности. Цене су на бази кредита — скупљи од GitHub Actions за мале тимове, али бржи захваљујући оптимизованим ранерима. Препоручује се за продукционе пројекте са захтевима за брзином.
Размотримо подешавање CI за Android пројекат коришћењем GitHub Actions-а. Pipeline извршава статичку анализу, компилацију и тестирање при сваком push-у и pull request-у у main грану. Минимална конфигурација траје 15 минута и не захтева спољне услуге.
name: Android CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
- run: ./gradlew ktlintCheck detekt
unit-tests:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
- uses: gradle/actions/setup-gradle@v4
- run: ./gradlew testDebugUnitTest
- uses: actions/upload-artifact@v4
with:
name: test-results
path: app/build/reports/tests/
Pipeline се састоји од два паралелна посла: lint (извршава статичку анализу) и unit-tests (зависи од lint — ако линтинг није прошао, тестови се не покрећу). Посао unit-tests отпрема извештај о тестовима као артефакт — тим га може прегледати у GitHub Actions интерфејсу без преузимања датотека локално.
Да бисте избегли пад CI због тривијалних грешака, подесите pre-push hook у Git-у или Gradle задатак који покреће исте провере локално. На пример: ./gradlew ktlintCheck detekt testDebugUnitTest. Ако локалне провере трају дуже од 3 минута — поделите их на брзе (линтер) и споре (тестови), покрећући брзе пре сваког комита, а споре само пре push-а.
Често постављана питања
CI се фокусира на интеграцију и верификацију кода (компилација + тестови), а CD додаје аутоматизацију примене. CI проверава да ли је код исправан; CD гарантује да тај исправан код може бити достављен корисницима. CI је предуслов за CD, али CD без CI не ради.
Минимална учесталост — једном дневно по програмеру. Идеална пракса — push у репозиторијум при свакој завршеној логичкој јединици рада (сваких 1–4 сата). Што је интеграција чешћа, мање је конфликата и лакше је њихово решавање. Ако између интеграција прође више од 2 дана — не користите CI.
За Android је оптималан GitHub Actions (бесплатан, једноставан за подешавање) или GitLab CI (сопствени ранери). За iOS — CircleCI (најбоља подршка за macOS) или Bitrise (специјализовани CI за мобилне пројекте). За cross-platform — GitLab CI са два ранера (Linux + macOS).
Да, али са резервама. UI тестови су спори (10–30 минута) и нестабилни (flaky). Оптимална стратегија: покрећите брзе тестове (јединичне + интеграционе) на сваки push, а UI тестове — на pull request, ноћу или пред release. Користите Device Farm или емулаторе у CI за UI тестове.
Метрике ефикасног CI: време компилације мање од 15 минута, проценат зелених компилација преко 85%, просечно време опоравка након пада мање од 30 минута. Ако компилација често пада — CI не помаже, већ одмаже. Преиспитајте тестове: уклоните flaky тестове, оптимизујте зависности, скратите време компилације.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође