Modul 9 — CI/CD
46. Pipeline jako kód a opakovaně použitelné šablony
Jak psát CI/CD pipeline jako verzovaný kód a jak z opakujících se částí vytvořit sdílené, znovupoužitelné šablony napříč projekty.
Úvod a kontext
Předchozí lekce ukázaly, jak sestavit jednu konkrétní CI/CD pipeline —
sestavení, testy, nasazení. Ve chvíli, kdy má tým nebo firma desítky
podobných projektů (např. mikroslužby se stejnou strukturou), se stejné
kroky pipeline začnou kopírovat z projektu do projektu. To je stejný
problém, jaký v aplikačním kódu řeší funkce a knihovny — a CI/CD nástroje
mají svou obdobu: opakovaně použitelné šablony pipeline. Tato lekce
ukazuje princip „pipeline jako kód“ v širším smyslu a konkrétní
mechanismy sdílení v GitLab CI a GitHub Actions.
Teorie
Pipeline jako kód
„Pipeline jako kód“ znamená, že definice CI/CD procesu (které kroky,
v jakém pořadí, s jakými podmínkami) žije jako verzovaný textový soubor
v repozitáři vedle aplikačního kódu, ne jako klikací konfigurace
v UI nějakého serveru. Výhody jsou stejné jako u Infrastructure as Code
(viz další modul): historie změn v Gitu, code review na změny pipeline,
možnost pipeline testovat a opakovaně použít, a žádná ruční konfigurace,
která by se dala v UI omylem rozbít bez záznamu.
Proč šablonizovat
Bez šablon se typicky opakují stejné bloky — instalace závislostí,
přihlášení do registry, nasazovací kroky — v .gitlab-ci.yml nebo
workflow souboru každého repozitáře zvlášť. Když se pak změní např.
verze nástroje pro bezpečnostní scan, je nutné to opravit ve všech
repozitářích ručně. Šablona centralizuje tuto logiku na jedno místo,
odkud si ji jednotlivé projekty jen „vypůjčí“ a případně parametrizují.
Mechanismy sdílení v GitLab CI
GitLab CI nabízí klíčové slovo include, kterým lze načíst definice
z jiného souboru — lokálního, z jiného projektu, nebo dokonce
vzdálené URL:
# .gitlab-ci.yml v konkrétním projektu
include:
- project: 'platform/ci-templates'
ref: main
file: '/templates/docker-build.yml'
- project: 'platform/ci-templates'
ref: main
file: '/templates/deploy-kubernetes.yml'
build:
extends: .docker-build-template
variables:
IMAGE_NAME: moje-appka
deploy-staging:
extends: .k8s-deploy-template
variables:
ENVIRONMENT: staging
NAMESPACE: moje-appka-staging
Klíčové slovo extends umožňuje, aby konkrétní job „zdědil“ definici
šablonového jobu (jehož jméno tradičně začíná tečkou, což ho zároveň
skryje jako samostatný spustitelný job) a přepsal jen to, co je pro daný
projekt specifické — typicky proměnné.
Samotná šablona v centrálním repozitáři platform/ci-templates:
# templates/docker-build.yml
.docker-build-template:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker build -t "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA" .
- docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA"
Mechanismus sdílení v GitHub Actions
GitHub Actions má pro tento účel reusable workflows — workflow
soubor, který lze zavolat z jiného workflow pomocí workflow_call,
a composite actions pro sdílení menších, opakujících se sekvencí
kroků.
Sdílený, znovupoužitelný workflow (uložený typicky v samostatném
repozitáři org/ci-templates):
# .github/workflows/docker-build.yml v repozitáři org/ci-templates
name: Reusable Docker build
on:
workflow_call:
inputs:
image-name:
required: true
type: string
secrets:
registry-token:
required: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Log in to registry
run: echo "${{ secrets.registry-token }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build and push
run: |
docker build -t ghcr.io/${{ github.repository }}/${{ inputs.image-name }}:${{ github.sha }} .
docker push ghcr.io/${{ github.repository }}/${{ inputs.image-name }}:${{ github.sha }}
Volání z konkrétního projektu:
# .github/workflows/ci.yml v konkrétním projektu
name: CI
on: [push]
jobs:
build:
uses: org/ci-templates/.github/workflows/docker-build.yml@main
with:
image-name: moje-appka
secrets:
registry-token: ${{ secrets.GHCR_TOKEN }}
Klíčové slovo uses s odkazem na cizí workflow soubor (org/repo/.github/
workflows/soubor.yml@ref) je ekvivalentem include/extends v GitLab
CI — parametrizace probíhá přes inputs a secrets deklarované v hlavičce
workflow_call.
Verzování šablon
Šablony samotné je vhodné verzovat — buď přes Git tag/ref (@main je
pohodlné, ale nebezpečné, protože se změna v šabloně projeví okamžitě
ve všech projektech bez varování; produkčně bezpečnější je pevná verze,
např. @v2.3.0), nebo přes samostatný release proces šablonového
repozitáře s changelogem, aby týmy mohly upgradovat řízeně.
Praktický příklad
Ukázka menší, ale časté šablony — composite action v GitHub Actions,
která sdílí instalaci závislostí a spuštění testů napříč více repozitáři
stejné technologie (Node.js):
# .github/actions/node-test/action.yml v repozitáři org/ci-templates
name: 'Node test'
description: 'Instaluje závislosti a spustí testy pro Node.js projekt'
inputs:
node-version:
description: 'Verze Node.js'
required: false
default: '20'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
shell: bash
- run: npm test
shell: bash
Použití v konkrétním projektu:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: org/ci-templates/.github/actions/node-test@v1
with:
node-version: '22'
Shrnutí
„Pipeline jako kód“ znamená verzovanou, recenzovanou definici CI/CD
procesu vedle aplikačního kódu. Jakmile se stejné kroky opakují napříč
projekty, vyplatí se je extrahovat do sdílené šablony — v GitLab CI
pomocí include/extends, v GitHub Actions pomocí reusable workflows
(workflow_call) nebo composite actions. Šablony samotné je vhodné
verzovat pevnou referencí, aby změna v šabloně neovlivnila všechny
závislé projekty nekontrolovaně a najednou.
Kontrolní otázky
- V čem je princip „pipeline jako kód“ podobný principu Infrastructure
as Code? - Jaký je rozdíl mezi
include/extendsv GitLab CI aworkflow_call
v GitHub Actions z pohledu výsledného efektu? - Proč je nebezpečné odkazovat na sdílenou šablonu přes
@mainmísto
pevné verze v produkčně důležité pipeline? - Mini cvičení: navrhněte, jaké dva až tři kroky z pipeline vašeho
(fiktivního) projektu byste extrahovali do sdílené šablony a proč
právě ty.
Lekce na sebe nejsou zamčené — libovolnou lekci můžete otevřít i označit jako hotovou v jakémkoliv pořadí.