GitLab CI — to wbudowany w GitLab system ciągłej integracji i dostarczania, automatyzujący budowanie, testowanie i wdrażanie aplikacji mobilnych poprzez pipeline’y w konfiguracji YAML. Według danych GitLab, 2024, platforma przetwarza ponad 300 milionów pipeline’ów miesięcznie i obsługuje zarówno chmurowe, jak i samodzielnie hostowane runnery.
Najważniejsze
GitLab CI — to część jednolitej aplikacji DevSecOps GitLab, obejmująca ciągłą integrację, dostarczanie i wdrażanie. System pojawił się w 2012 roku jako osobny projekt, ale został zintegrowany bezpośrednio z GitLab. Główna zasada — konfiguracja w kodzie (Configuration as Code) poprzez plik .gitlab-ci.yml w katalogu głównym repozytorium. GitLab CI jest dostępny zarówno w chmurowej wersji SaaS, jak i w samodzielnie zarządzanej instalacji.
Dla tworzenia aplikacji mobilnych GitLab CI oferuje automatyzację budowania APK i IPA, uruchamianie testów instrumentalnych, statyczną analizę kodu, podpisywanie aplikacji i publikację w sklepach. Platforma obsługuje obrazy Docker dla niestandardowych środowisk, co pozwala na preinstalację Android SDK, NDK, Xcode i innych narzędzi. Wbudowany Container Registry ułatwia przechowywanie i dystrybucję obrazów w zespole.
Architektura GitLab CI składa się z trzech kluczowych komponentów. GitLab Runner — to agent wykonujący joby. Runnery dzielą się na shared (udostępniane przez GitLab), group (dla grupy projektów) i specific (dla jednego projektu). Każdy runner rejestruje się z określeniem executor: Shell, Docker, Kubernetes lub VirtualBox. GitLab Runner obsługuje auto-skaling do przetwarzania szczytowych obciążeń.
Pipeline — to zbiór stage’ów wykonywanych sekwencyjnie. Wewnątrz jednego stage’a joby są wykonywane równolegle. Typowa struktura dla projektu mobilnego: build → test → deploy. Jeśli job na stage’u test zakończył się błędem, deploy nie jest uruchamiany. Można skonfigurować ręczne uruchamianie (when: manual) dla wdrażania. Obsługiwane są również triggery multi-project pipelines dla złożonych scenariuszy CI/CD między repozytoriami.
Docker executor — najpopularniejszy dla CI/CD aplikacji mobilnych. Każdy job uruchamiany jest w czystym kontenerze Docker, co gwarantuje izolację i powtarzalność. Dla kompilacji Android używany jest obraz android-sdk z preinstalowanym SDK, dla iOS — macOS runner z executorem Shell.
Plik .gitlab-ci.yml definiuje pipeline w formacie YAML. Główne sekcje: image (obraz Docker), stages (lista etapów), variables (zmienne środowiskowe), before_script (polecenia przed każdym jobem) oraz same joby z sekcjami script, artifacts, cache. GitLab CI obsługuje include — dołączanie zewnętrznych plików YAML do ponownego wykorzystania wspólnych konfiguracji między projektami.
Variables w GitLab CI mogą być ustawione na kilku poziomach: globalne w UI, w pliku konfiguracyjnym, w ustawieniach grupy i projektu. Priorytet zmiennych określa hierarchia: trigger variables mają najwyższy priorytet, następnie CI/CD variables z UI, a następnie z .gitlab-ci.yml. Zmienne można chronić (protected), co udostępnia je tylko dla chronionych branchy i tagów.
image: openjdk:17-jdk-slim
variables:
ANDROID_SDK_VERSION: "35"
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
stages:
- build
- test
- deploy
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- .gradle/
Job generate-apk buduje projekt Gradle i zapisuje APK jako artefakt. Artefakty są przekazywane między stage’ami — job deploy może wykorzystać APK z build. Czas przechowywania artefaktów jest konfigurowany przez expire_in.
generate-apk:
stage: build
script:
- ./gradlew assembleRelease
artifacts:
paths:
- app/build/outputs/apk/release/
expire_in: 1 day
Przy wyborze między GitLab CI a GitHub Actions dla projektu mobilnego ważne jest uwzględnienie infrastruktury zespołu. GitLab CI udostępnia wbudowany Container Registry, który można wykorzystać do przechowywania obrazów Docker z Android SDK. GitHub Actions opiera się na GitHub Packages lub zewnętrznych rejestrach. GitLab ma również wbudowany SAST (Static Application Security Testing) do analizy kodu pod kątem podatności.
GitLab CI oferuje bardziej elastyczny model runnerów — obsługuje Kubernetes executor, auto-skaling i niestandardowe obrazy. GitHub Actions wygrywa w integracji z ekosystemem GitHub i marketplace akcji. GitLab CI wymaga ręcznej konfiguracji wielu zadań, które w GitHub Actions są rozwiązywane gotową akcją.
Z punktu widzenia CI/CD dla projektów mobilnych: GitLab CI lepiej nadaje się dla firm już używających GitLab Self-Managed i wymagających self-hosted runnerów z Docker/Kubernetes. GitHub Actions jest wygodniejszy dla małych zespołów korzystających z chmurowego GitHub, ceniących gotowe akcje i prostotę konfiguracji.
| Cecha | GitLab CI | GitHub Actions |
|---|---|---|
| Konfiguracja | .gitlab-ci.yml | .github/workflows/*.yml |
| Runner | Self-hosted + shared | Hosted + self-hosted |
| Executory | Docker, K8s, Shell | VM (Ubuntu, macOS, Win) |
| Sklep z akcjami | Brak (szablony CI) | Marketplace (15k+ akcji) |
| Budowanie iOS | macOS runner lub K8s | macOS hosted runner |
Pełny pipeline dla Androida obejmuje: lint, testy jednostkowe, budowanie i wdrożenie w Firebase App Distribution. Pipeline wykorzystuje obraz Docker z Android SDK, cachowanie Gradle i równoległe wykonywanie lint i testów w jednym stage’u. Takie podejście skraca całkowity czas pipeline’u, ponieważ taski lint i test nie są od siebie zależne.
Dla projektów iOS struktura pipeline’u różni się ze względu na konieczność macOS runnera i podpisywania kodu. Typowy pipeline iOS obejmuje: instalację CocoaPods lub SPM, uruchomienie testów na symulatorze, archiwizację projektu Xcode, eksport IPA i przesłanie do TestFlight. GitLab CI dla iOS używa macOS runnerów — albo GitLab SaaS macOS runnerów z ograniczeniami czasowymi, albo self-hosted runnera na Mac mini lub MacStadium.
image: androidsdk/android-35:latest
stages:
- lint
- test
- build
- deploy
lint-check:
stage: lint
script: ./gradlew lint
unit-tests:
stage: test
script: ./gradlew test
assemble-release:
stage: build
script: ./gradlew assembleRelease
artifacts:
paths: [app/build/outputs/apk/release/]
deploy-firebase:
stage: deploy
script:
- firebase appdistribution:distribute
--app $FIREBASE_APP_ID
--token $FIREBASE_TOKEN
--groups testers
Optymalizacja pipeline’ów budowania mobilnego w GitLab CI wymaga uwagi na szczegóły. Prawidłowa konfiguracja cache i artifacts pozwala skrócić czas budowania kilkukrotnie. Do analizy wydajności GitLab udostępnia CI/CD Analytics — pulpit z metrykami czasu trwania pipeline’ów, obciążenia runnerów i wąskich gardeł. Analizuj te metryki regularnie, aby znaleźć możliwości optymalizacji. Ustawienie resource_group blokuje równoległe uruchamianie jednego pipeline’u — jest to przydatne do zapobiegania konfliktom podczas wdrażania.
Ważna jest również strategia gałęzi dla CI. Zaleca się uruchamianie pełnego pipeline’u tylko dla gałęzi main i release, a dla gałęzi feature — tylko lint i testy jednostkowe. Oszczędza to minuty runnerów i przyspiesza informację zwrotną dla programistów. GitLab CI obsługuje workflow:rules — warunkowe reguły włączania i wyłączania jobów w zależności od gałęzi, zmienionych plików lub zmiennych środowiskowych.
Cachowanie zależności — główny sposób przyspieszenia. GitLab CI cachuje .gradle, Pods i node_modules między uruchomieniami. Klucz cache zawiera $CI_COMMIT_REF_SLUG lub hash pliku lock. Czas budowania projektu Android skraca się z 10–15 do 2–4 minut przy prawidłowym cachowaniu. Cache może być rozproszony — GitLab obsługuje cache:key z fallbackiem na poprzednie klucze.
Obraz Docker z preinstalowanymi narzędziami oszczędza czas na instalację. Zaleca się stworzenie niestandardowego obrazu z Android SDK, NDK i wymaganym poziomem API. Równoległe wykonywanie jobów (lint, test, assemble) w różnych stage’ach skraca całkowity czas pipeline’u. Pull policies dla obrazów (if-not-present) przyspieszają start jobów. Można również użyć dependency proxy do cachowania obrazów na poziomie instancji GitLab.
Kolejny ważny aspekt optymalizacji — wykorzystanie artefaktów między etapami. Ciężkie pliki APK i IPA lepiej przekazywać przez dependency, niż przebudowywać w każdym jobie. Dla dużych projektów z dziesiątkami modułów zaleca się włączenie Gradle Build Cache na poziomie pipeline’u i skonfigurowanie remote cache na wspólnym magazynie. Timeout dla każdego joba należy ustawić na podstawie oczekiwanego czasu budowania — zapobiega to zawieszonym procesom.
cache:
key: $CI_COMMIT_REF_SLUG
paths:
- .gradle/
- app/build/
image:
name: registry.example.com/android-builder:3.5
pull_policy: if-not-present
Często zadawane pytania
Na GitLab.com darmowy plan obejmuje 400 minut CI/CD miesięcznie i 5 użytkowników. Premium ($29/mies) daje 10000 minut i więcej równoległych jobów. Self-managed GitLab nie ma ograniczenia minut.
Użyj gotowego obrazu Docker androidsdk/android-35 lub zainstaluj SDK przez sdkmanager w before_script. W variables podaj ANDROID_SDK_ROOT i ANDROID_NDK_HOME dla poprawnego działania Gradle.
GitLab CI oferuje wbudowany Container Registry, integrację z Kubernetes i self-hosted auto-skaling. GitHub Actions wygrywa w liczbie gotowych akcji i prostocie dla małych zespołów.
Tak, ale dla iOS wymagany jest macOS runner. Można użyć GitLab SaaS macOS runnerów (ograniczone) lub skonfigurować self-hosted runner na Mac Mini. GitLab sam nie udostępnia chmurowej infrastruktury macOS.
Przez artifacts — pliki jednego joba są przekazywane do innego joba w ramach pipeline’u. Przez cache — dla zależności między uruchomieniami. Przez CI/CD variables — dla wartości tekstowych i tokenów.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również