Definicja Gitlab CI może stać się naprawdę złożona. Aby zredukować nadmiarowość można użyć wielu przydatnych funkcji i składni, takich jak !reference.

Chociaż składnia YAML w Gitlab CI nie jest tak przyjazna, jak wielu mogłoby oczekiwać, to jednak może zdziałać cuda. Tagi !reference to jedna z tych funkcji, które mogą pomóc w uporządkowaniu definicji CI w sposób, który zapewni łatwe utrzymanie w przyszłości.

Wyobraźcie sobie taki prosty scenariusz:

job1:
  script:
    - echo "Diff base is '$CI_MERGE_REQUEST_DIFF_BASE_SHA'"
    - GIT_DIFF_CHANGED_FILES=$(git diff --diff-filter=ACMR --name-only ${CI_MERGE_REQUEST_DIFF_BASE_SHA}...)
    - echo "$(echo $GIT_DIFF_CHANGED_FILES | wc -l) file(s) changed"

job2:
  script:
    - echo "Diff base is '$CI_MERGE_REQUEST_DIFF_BASE_SHA'"
    - GIT_DIFF_CHANGED_FILES=$(git diff --diff-filter=ACMR --name-only ${CI_MERGE_REQUEST_DIFF_BASE_SHA}...)
    - echo $GIT_DIFF_CHANGED_FILES

Wykrywanie różnic w Git jest tam nadmiarowe, jest dokładnie takie samo w obu zadaniach. Może to prowadzić do niespójności między zadaniami, jeśli coś wymaga poprawy — jedno z zadań może zostać zaktualizowane, a drugie nie. Możemy to łatwo poprawić za pomocą !reference:

.diff:
  script:
    - echo "Diff base is '$CI_MERGE_REQUEST_DIFF_BASE_SHA'"
    - GIT_DIFF_CHANGED_FILES=$(git diff --diff-filter=ACMR --name-only ${CI_MERGE_REQUEST_DIFF_BASE_SHA}...)

job1:
  script:
    - !reference [.diff, script]
    - echo "$(echo $GIT_DIFF_CHANGED_FILES | wc -l) file(s) changed"

job2:
  script:
    - !reference [.diff, script]
    - echo $GIT_DIFF_CHANGED_FILES

Teraz wspólna logika jest wyodrębniana do szablonu (zadanie zaczynające się od .), a inne skrypty wykorzystują ten kod poprzez odwołanie. Jeśli trzeba zmienić logikę wykrywania diff’u, będzie to miało odzwierciedlenie w obu zadaniach. Mimo, że można to osiągnąć również anchorami, !reference ma jedną dużą zaletę: sekcja i odwołania do niej mogą znajdować się w różnych plikach, podczas gdy definicja anchor’a musi być w tym samym pliku, co jej użycie.

Do dziś myślałem, że !reference ma jedną wadę: brak wsparcia dla zagnieżdżenia. Dokumentacja mówi:

Nie możesz ponownie użyć sekcji, która już zawiera znacznik !reference. Obsługiwany jest tylko jeden poziom zagnieżdżania.

Ale wygląda na to, że zagnieżdżanie jednak działa w Gitlab 14.10, więc stworzyłem zgłoszenie i poprosiłem o podanie aktualnych informacji (i najprawdopodobniej zaktualizowanie dokumentacji). Odkryliśmy to przypadkiem, kolega użył zagnieżdżonych referencji, bo nie wiedział, że nie można tego robić 😅. Teraz możemy poprawić niektóre fragmenty naszej definicji Gitlab CI, ale prawdopodobnie poczekamy na odpowiedź, by poznać aktualne ograniczenia (jeśli występują).

Miłego odnoszenia!