
#010 - GitLab - CI/CD embedded #02
Na początku przypominam, że to wpis z dłuższej serii i za pierwszym razem zalecane jest przejrzenie wszystkich części.
- wpis 1 - budowanie HelloWorld w C na GitLabie
- wpis 2 - Dodatkowe informacje na temat skryptów budujących
- wpis 3 - CubeIDE - przygotowanie testowego projektu
- wpis 4 - CubeIDE - przygotowanie obrazu dockera do budowania
- wpis 5 - CubeIDE - budowanie projektu
- wpis 6 - rozbudowanie skryptów budujących
- wpis 7 - automatyczne testy jednostkowe
- wpis 8 - raport pokrycia kodu testami
W poprzednim wpisie uzyskaliśmy podstawowy plik .gitlab-ci.yml - przypomnę jego zawartość:
stages:
- build
release:
stage: build
image: gcc
script:
- gcc main.c -o app
artifacts:
paths:
- app
Ten wpis będzie dotyczył kilku usprawnień - celowo na małym pliku, a nie na końcowym z budowaniem na CubeIDE - aby modyfikacje były dobrze widoczne.
Job “manualny”
Poprzedni plik wymuszał build automatycznie po każdym pushu na serwer (nie budowały się automatycznie commity pośrednie, tylko ostatni wypchnięty w danym pushu). Jednak w zależności od workflow mogą się zdarzyć commity, które same w sobie się nie budują - jeśli chcemy jakąś funkcjonalność robić na kilka commitów, aby mieć ładną historię w gitBlame.
GitLab wtedy prześle maila z informacją o nieudanym buildzie - co nie jest wtedy potrzebne. Powiadomienia takie można wyłączyć - jednak wtedy utracimy je też z tych ważnych commitów.
W darmowym koncie “oszczędnością” z buildów manualnych jest także zmniejszenie czasu pracy serwerów CI/CD.
Modyfikacja w skrypcie jest banalna - sprowadza się do dopisania linijki:
when: manual
Tutaj można znaleźć rozszerzenie tematu - puls opis jak ten mechanizm można wykorzystać do wymuszenia “akceptacji” dla danej paczki przez osoby do tego uprawnione - https://about.gitlab.com/blog/2020/02/20/protecting-manual-jobs/.
Przykładem może być wdrożenie aplikacji webowej na serwer produkcyjny, a w embedded - przesłanie paczki firmware do podpisania na zewnętrznym serwerze - tzn “secureServer”, czy jakaś procedura wygenerowania kluczy.
Job tylko dla wybranych branchy
Można ograniczyć możliwość wykonania danego Joba do wybranych branchy z wykorzystaniem:
only:
- master
Lub zrobić negację tego - czyli dla wszystkich innych oprócz wybranych:
except:
- master
W podanych nazwach można używać regexów - więc jeśli w firmie istnieje standard nazywania branchy - może to sporo ułatwić. Przykład:
job:
# use regexp
only:
- /^feature-.*$/
Zmienne do wykorzystania w skrypcie
GitLab udostępnia wiele zmiennych środowiskowych, które można wykorzystać w skrypcie budowania - chyba najczęstsze ich wykorzystanie to modyfikacja nazwy wynikowego pliku artefaktów - można tam zawszeć np datę budowania, wersję, branch, SHA commitu.
Przykład:
artifacts:
name: "${CI_PROJECT_NAME}-${CI_COMMIT_BRANCH}-bin-${CI_JOB_NAME}-${CI_COMMIT_SHA}"
paths:
- "app"
Zbiór zmiennych jakie domyślnie możemy użyć: https://docs.gitlab.com/ee/ci/variables/
Warto zaznaczyć, że jeśli w projekcie do budowania używane są skrypty - to podczas uruchomienia ich na serwerze budującym też będą miały dostęp do tego samego zestawu zmiennych środowiskowych. W taki sposób można rozróżniać, czy projekt jest budowany lokalnie, czy na serwerze i np. oznaczyć paczkę jako deweloperską.
Jeśli w buildzie wynikowe nazwy plików do artefaktów itp są powiązane z nazwą Joba itp. można ich też użyć w sekcji “paths”.
Innym przykładem użycia jest wpisywanie np. SHA commitu do modułu oznaczania wersji firmware, który będzie potem dostępny z poziomu kodu.
Przy okazji podpowiedź - jeśli nie jest potrzebne pełne SHA można pobrać skróconą wersję na 2 sposoby.
Formatując string:
${CI_COMMIT_SHA:0:8}
lub w nowszych wersjach GitLaba dodano zmienną “$CI_COMMIT_SHORT_SHA”.
Submoduly
Jeśli projekt wykorzystuje submoduły Gita - polecam zawsze dodać w skrypcie linijkę o tym, aby je dobrze pobierać - sprowadza się to do tego na początku pliku:
.global-variables: &global-variables
GIT_SUBMODULE_STRATEGY: recursive
Więcej na ten temat: https://docs.gitlab.com/ee/ci/git_submodules.html
Submoduły, a pobieranie całości projektu
Trochę poboczny temat - w GitLabie jest możliwość pobrania całego repozytorium jako archiwum - jest to ta ikonka:
W przypadku używania submodułów pobierzemy jednak tam puste katalogi.
Obejście problemu - osobny build, który pobiera całe repozytorium z submodułami i je pakuje w archiwum - dodatkowo można wtedy ten plik odpowiednio ponazywać/otagować itp. Może się okazać przy zakykaniu projektu w firmie, że dla celów dokumentacyjnych wymagana jest też kopia “offline” źródeł - wtedy tak to trzeba zrobić - do templtki tego już nie dodawałem.
Podsumowanie
Zmodyfikowany szablon o usprawnienia z tego wpisu:
.global-variables: &global-variables
GIT_SUBMODULE_STRATEGY: recursive
stages:
- build
release:
stage: build
when: manual
image: gcc
script:
- gcc main.c -o app
artifacts:
name: "${CI_PROJECT_NAME}-${CI_COMMIT_BRANCH}-bin-${CI_JOB_NAME}-${CI_COMMIT_SHA}"
paths:
- app
W testowym projekcie jest to commit:
Najważniejsze co udało się osiągnąć na koniec tego wpisu:
- możliwość uruchomienia buildów manualnych zamiast automatycznych
- wykorzystanie zmiennych środowiskowych przy procesie budowania - generowanie nazw artefaktów
- jak poradzić sobie z projektem, który wykorzystuje submoduły GITa