GH GambleHub

CI/CD конвеєри: GitHub Actions, GitLab CI

CI/CD конвеєри: GitHub Actions, GitLab CI

1) Завдання CI/CD і місце в платформі

CI/CD - це безперервна збірка, тестування і доставка змін з репозиторію в робочі оточення. Цілі:
  • Швидкість і передбачуваність релізів (короткий lead time).
  • Якість (автотести, статичний/динамічний аналіз).
  • Безпека ланцюжка поставки (підпис артефактів, контроль доступів).
  • Надійність (канареечні деплої, швидкий відкат).
  • Спостережуваність (трасування і метрики на кожному етапі).

Ключові принципи: «pipeline as code», іммутабельні артефакти, «build once - run many», «shift-left security», «least privilege», детерміновані збірки.

2) Архітектурні патерни конвеєрів

Stage-gate: build → test → security → package → deploy → post-deploy checks.
Fan-out/Fan-in: паралельні матричні збірки (мови/платформи) з об'єднанням результатів.
Promotion: один і той же артефакт просувається через оточення (dev → stage → prod), а не пересобирається.
Trunk-based + короткі гілки: мінімізація дрейфу, автоматизовані перевірки на PR/MR.
Reusable: перевикористовувані workflow/шаблони (Actions: reusable workflows; GitLab: includes/child-pipelines).
GitOps (опціонально): поділ «збірки» і «доставки» (Argo CD/Flux стежать за декларативним репо оточень).

3) Безпека ланцюжка поставки (supply chain)

Ідентифікація: OIDC-федерація від runner'a до хмари (без довгоживучих ключів).
Секрети: централізоване сховище, обмеження контексту, заборона на виведення в логи.
Підпис артефактів/контейнерів (cosign/Sigstore), перевірка підпису в admission-контролі.
SBOM (CycloneDX/SPDX) і SCA, SAST/DAST/Container Scan - «обов'язкові ворота».
Політики: OPA/Conftest для IaC/маніфестів, «no latest», заборона привілейованих контейнерів.
Ізоляція runner'ів: prod-раннери в приватній мережі, відокремити від публічного інтернету вихідних доступів.

4) GitHub Actions - структура та практики

4. 1 Структура workflows

'.github/workflows/.yml'- тригери ('on: push, pull_request, schedule, workflow_call`).
Reusable workflows для стандартизації (лінтер, SCA, контейнерне складання, деплою).

4. 2 Приклад: багатостадійний пайплайн з OIDC і підписом образу

yaml name: ci-cd

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

permissions:
id-token: write  # для OIDC contents: read packages: write

jobs:
build_test_matrix:
runs-on: ubuntu-latest strategy:
matrix:
node: [18, 20]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4 with: { node-version: ${{ matrix. node }} }
- name: Cache npm uses: actions/cache@v4 with:
path: ~/.npm key: npm-${{ runner. os }}-${{ matrix. node }}-${{ hashFiles('/package-lock. json') }}
- run: npm ci
- run: npm run lint && npm test -- --ci

docker_build_sign:
runs-on: ubuntu-latest needs: build_test_matrix steps:
- uses: actions/checkout@v4
- name: Login to GHCR uses: docker/login-action@v3 with:
registry: ghcr. io username: ${{ github. actor }}
password: ${{ secrets. GITHUB_TOKEN }}
- name: Build image run:
docker build --pull --no-cache -t ghcr. io/org/app:${{ github. sha }}.
docker push ghcr. io/org/app:${{ github. sha }}
- name: Generate SBOM uses: anchore/syft-action@v0 with:
image: ghcr. io/org/app:${{ github. sha }}
format: cyclonedx-json output-file: sbom. json
- name: Cosign sign (OIDC)
uses: sigstore/cosign-installer@v3
- name: Sign image run:
cosign sign ghcr. io/org/app:${{ github. sha }} \
--yes \
--identity-token $ACTIONS_ID_TOKEN_REQUEST_TOKEN \
--rekor-url https://rekor. sigstore. dev

deploy_stage:
runs-on: ubuntu-latest needs: docker_build_sign environment:
name: stage url: https://stage. example. com steps:
- uses: actions/checkout@v4
- name: Assume cloud role via OIDC uses: aws-actions/configure-aws-credentials@v4 with:
role-to-assume: arn:aws:iam::123456789012:role/github-deployer aws-region: eu-central-1
- name: Helm deploy (canary 10%)
run:
helm upgrade --install app charts/app \
--set image. tag=${{ github. sha }} \
--set canary. enabled=true --set canary. traffic=10
- name: Smoke checks run:./scripts/smoke. sh

promote_prod:
runs-on: ubuntu-latest needs: deploy_stage environment:
name: production url: https://app. example. com concurrency: prod-release steps:
- name: Manual approval gate run: echo "Requires environment approvers in repo settings"
- name: Promote canary → 100% (blue-green)
run:
helm upgrade --install app charts/app \
--set image. tag=${{ github. sha }} \
--set canary. enabled=false
- name: Post-deploy checks & rollback on SLO breach run:./scripts/verify_or_rollback. sh
Ключі:
  • 'permissions'зведені до мінімуму, включений'id-token: write'для OIDC.
  • Environments з approvers і URL,'concurrency'захищає від гонок.
  • Канареечное включення трафіку і автоматичний відкат по SLO.

4. 3 Reusable workflow (приклад виклику)

yaml jobs:
security_suite:
uses: org/.github/.github/workflows/security. yml@v1 with:
severity_threshold: high

5) GitLab CI - структура і практики

5. 1 Базова структура

`.gitlab-ci. yml'в корені; ключові сутності: `stages`, `jobs`, `rules`, `needs`, `artifacts`, `environments`, `manual`.
Reuse: `include:'(локальні/remote шаблони), child/parent pipelines для складних монорепо.

5. 2 Приклад: матриця, кеш, підпис, оточення і approvals

yaml stages: [lint, test, build, security, deploy]

variables:
DOCKER_TLS_CERTDIR: "" # docker: dind acceleration
IMAGE_TAG: $CI_COMMIT_SHA

lint:
stage: lint image: node:20 script:
- npm ci
- npm run lint cache:
key: "npm-${CI_COMMIT_REF_SLUG}"
paths: [node_modules/]
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"

test:
stage: test image: node:20 parallel:
matrix:
- NODE_VERSION: ["18", "20"]
script:
- nvm install $NODE_VERSION          true
- npm ci
- npm test -- --ci artifacts:
when: always reports:
junit: report. xml

build_image:
stage: build image: docker:26. 1 services: [ "docker:26. 1-dind" ]
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:$IMAGE_TAG.
- docker push $CI_REGISTRY_IMAGE:$IMAGE_TAG artifacts:
expire_in: 1 week paths: [ "sbom. json" ]
after_script:
- syft $CI_REGISTRY_IMAGE:$IMAGE_TAG -o cyclonedx-json > sbom. json

security_scans:
stage: security image: alpine:3. 20 script:
- trivy image --exit-code 0 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$IMAGE_TAG rules:
- if: '$CI_COMMIT_BRANCH == "main"'

deploy_stage:
stage: deploy image: bitnami/kubectl:1. 30 environment:
name: stage url: https://stage. example. com on_stop: stop_stage script:
- kubectl set image deploy/app app=$CI_REGISTRY_IMAGE:$IMAGE_TAG -n stage
-./scripts/smoke. sh needs: [build_image, security_scans]
when: manual allow_failure: false

stop_stage:
stage: deploy image: bitnami/kubectl:1. 30 environment:
name: stage action: stop script:
- kubectl rollout undo deploy/app -n stage

deploy_prod:
stage: deploy image: alpine/k8s:1. 30. 2 environment:
name: production url: https://app. example. com rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual allow_failure: false script:
-./scripts/canary_traffic. sh 10
-./scripts/verify_or_rollback. sh
Ключі:
  • `parallel. matrix'імітує матричні збірки.
  • 'artifacts'+ звіти тестів.
  • Environments з'on _ stop', ручні'when: manual'для approvals.
  • DIND для збірки образу (краще - Kaniko/BuildKit в k8s-раннері).

5. 3 Child pipelines і include для монорепо

yaml include:
- local:.gitlab/ci/includes/security. yml
- project: org/platform/pipelines file: /k8s/deploy. yml ref: v1

stages: [prepare, component_a, component_b, deploy]

component_a:
stage: component_a trigger:
include:.gitlab/ci/component_a. yml strategy: depend

component_b:
stage: component_b trigger:
include:.gitlab/ci/component_b. yml strategy: depend

6) Монорепозиторії та багатосервісність

Directory-based ownership: CODEOWNERS і scoped-тести по шляхах.
Incremental builds: визначаємо порушені пакети/чарти; кеш по ключах шляхів і lock-файлам.
Dynamic pipelines: child-pipelines/' workflow _ call'запускаються тільки для змінених компонентів.
Версіонування: semver по кожному модулю, changelog на release-етапі.

7) Кешування і прискорення

Контент-адресні кеші (hashFiles/lockfile).
Роздільний кеш для залежностей і артефактів.
Pre-warm runner images (toolchains, SDK).
Локальні дзеркала пакетів (npm/pip/maven) і контейнерний registry-кеш.

8) Релізні стратегії і відкат

Canary: поступове нарощування відсотка трафіку; авто-стоп при деградації SLO.
Blue-Green: паралельні стеки, миттєве перемикання.
Shadow: дублювання запитів без впливу на клієнта.
Feature flags: rollout на рівні прапора, а не релізу.
Rollback: чіткі скрипти «однією кнопкою», версія артефакту зберігається в метаданих релізу.

9) Інфраструктура та GitOps

IaC: Terraform/Ansible/Helm управляються в окремих репо; policy-as-code як ворота.
GitOps-контур: Argo CD/Flux спостерігають репо з маніфестами оточень; конвеєр лише створює артефакт і оновлює версії в Git.
Переваги: явна історія змін оточення, ідемпотентність, стандартні відкати через Git.

10) Спостережуваність CI/CD

DORA-метрики: частота деплоїв, час від коміту до продакшну, відсоток відмов, MTTR.
Telemetry: час черг job'ів, тривалість стадій, hit-rate кешу, частота flaky-тестів.
Логи безпеки: хто ініціював реліз, які ворота пройдені, які винятки видані.

11) Управління доступом і approvals

Branch protection і обов'язкові перевірки.
Environment-approvals: окремі списки approvers на stage/prod.
JIT-доступ для ручних кроків, журналювання сесій.
Поділ обов'язків: різні ролі для «пише код», «схвалює», «випускає».

12) Часті помилки (анти-патерни)

Довгоживучі хмарні ключі в секретах репо замість OIDC-ролей.
Збірка різних артефактів для stage і prod (порушення «build once»).
'latest'теги і mutable-образи.
Публікація секретів в логах кроків (невідключений masking).
Один загальний public-runner для прод-деплоїв.
Відсутність «воріт» безпеки (SAST/SCA/Policy) і post-deploy перевірок.

13) Чек-лист впровадження (0-60 днів)

0-15 днів

Налаштувати trunk-based, PR/MR правила, обов'язкові статичні перевірки.
Включити OIDC-федерацію до хмари; мінімальні'permissions'.
Рознести runner'и: публічні - для CI, приватні - для CD.

16-30 днів

Додати SBOM, підпис образів; у кластері - перевірка підпису.
Ввести canary/blue-green; авто-rollback по SLO.
Кеш залежностей і артефактів, pre-warm образів.

31-60 днів

Розділити збірку і доставку (GitOps), policy-as-code ворота.
Налагодити DORA-метрики і алерти по деградації пайплайнів.
Шаблонізувати пайплайни (reusable/child) для всіх сервісів.

14) Практичні поради щодо надійності

Підтримуйте маленькі, швидкі пайплайни (10-12 хв до сигналу на PR).
Вбивайте flaky-тести: quarantine-мітки + паралельний фікс.
Не змішуйте CI-артефакти і release-артефакти; зберігайте метадані (commit, часу, SBOM, підпису).
Дайте розробникам локальні скрипти, ідентичні крокам конвеєра (dev-prod parity).

15) Шаблони для перевикористання

15. 1 GitHub Actions - security reusable workflow (спрощено)

yaml name: security-suite on:
workflow_call:
inputs:
severity_threshold:
type: string required: false default: high jobs:
sast_sca:
runs-on: ubuntu-latest steps:
- uses: actions/checkout@v4
- run:./sec/sast. sh --threshold ${{ inputs. severity_threshold }}
- run:./sec/sca. sh --format cyclonedx-json --out sbom. json artifacts: # if using actions/upload-artifact
- sbom. json

15. 2 GitLab - включений шаблон deploy (спрощено)

yaml
.deployment_template:
image: alpine/k8s:1. 30 script:
- helm upgrade --install $APP charts/$APP --set image. tag=$IMAGE_TAG rules:
- if: '$CI_COMMIT_BRANCH == "main"'

16) Висновок

GitHub Actions і GitLab CI надають зрілі механізми для швидкого і безпечного циклу «код → прод». Ключ до успіху - стандартизація та безпека: OIDC замість ключів, підпис і SBOM, ворота якості, єдиний артефакт з промоушеном, GitOps-доставка і спостережуваність через DORA. Будуйте пайплайни як продукт: вимірюйте, спрощуйте, прискорюйте - і релізи стануть рутиною, а не подією.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Telegram
@Gamble_GC
Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.