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:

obr

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