GH GambleHub

CI/CD pipelines: GitHub Actions, GitLab CI

CI/CD pipelines: GitHub Actions, GitLab CI

1) CI/CD Task and Platform Space

CI/CD is the continuous assembly, testing, and delivery of changes from the repository to production environments. Objectives:
  • Speed ​ ​ and predictability of releases (short lead time).
  • Quality (auto tests, static/dynamic analysis).
  • Supply chain security (artifact signing, access control).
  • Reliability (canary deposits, fast rollback).
  • Observability (trace and metrics at each stage).

Key principles: "pipeline as code," immutable artifacts, "build once - run many," "shift-left security," "left privilege," deterministic assemblies.

2) Architectural patterns of conveyors

Stage-gate: build → test → security → package → deploy → post-deploy checks.
Fan-out/Fan-in: parallel matrix assemblies (languages/platforms) with concatenation of results.
Promotion: the same artifact is promoted through the environment (dev → stage → prod), and not reassembled.
Trunk-based + short branches: drift minimization, automated checks on PR/MR.
Reusable: reusable workflows GitLab: includes/child-pipelines).
GitOps (optional): separation of "assembly" and "delivery" (Argo CD/Flux monitor declarative repo environments).

3) Supply chain security

Identification: OIDC federation from runner to cloud (without long-lived keys).
Secrets: centralized storage, context restriction, prohibition on logging.
Signature of artifacts/containers (cosign/Sigstore), verification of signature in admission control.

SBOM (CycloneDX/SPDX) and SCA, SAST/DAST/Container Scan - "mandatory gate."

Politicians: OPA/Conftest for IaC/manifestos, "no latest," banning privileged containers.
Isolation of runners: prod-runners in a private network, separate outgoing access from the public Internet.

4) GitHub Actions - Structure and Practices

4. 1 workflows structure

`.github/workflows/.yml` — триггеры (`on: push, pull_request, schedule, workflow_call`).
Reusable workflows for standardization (linter, SCA, container assembly, deployment).

4. 2 Example: multi-stage pipeline with OIDC and image signature

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
Keys:
  • 'permissions' are minimized, 'id-token: write'is enabled for OIDC.
  • Environments with approvers and URL, 'concurrency' protects against racing.
  • Canary inclusion of traffic and automatic rollback over SLO.

4. 3 Reusable workflow (call example)

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

5) GitLab CI - Structure and Practices

5. 1 Basic structure

`.gitlab-ci. yml 'at the root; key entities: 'stages', 'jobs', 'rules', 'needs', 'artifacts', 'environments', 'manual'.
Reuse: 'include:' (local/remote patterns), child/parent pipelines for complex monorepos.

5. 2 Example: matrix, cache, signature, environments and 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
Keys:
  • `parallel. matrix 'simulates matrix assemblies.
  • 'artifacts' + test reports.
  • Environments with 'on _ stop', manual 'when: manual' for approvals.
  • DIND for building an image (better - Kaniko/BuildKit in the k8s runner).

5. 3 Child pipelines and include for monorepos

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) Monorepository and multiservice

Directory-based ownership: CODEOWNERS and scoped tests by path.
Incremental builds: identify affected packages/charts; cache by path keys and lock files.
Dynamic pipelines: child-pipelines/' workflow _ call 'run only for changed components.
Versioning: semver for each module, changelog at the release stage.

7) Caching and acceleration

Content address caches (hashFiles/lockfile).
Separate cache for dependencies and artifacts.
Pre-warm runner images (toolchains, SDK).
Local packet mirrors (npm/pip/maven) and container registry cache.

8) Release strategies and rollback

Canary: gradually increasing the percentage of traffic; auto-stop during SLO degradation.
Blue-Green: parallel stacks, instant switching.
Shadow: duplicate requests without affecting the client.
Feature flags: rollout at flag level, not release level.
Rollback: clear one-button scripts, the artifact version is stored in the release metadata.

9) Infrastructure and GitOps

IaC: Terraform/Ansible/Helm are managed in separate repos; policy-as-code as a gate.
GitOps-contour: Argo CD/Flux observe repo with manifestos of environments; the pipeline only creates an artifact and updates versions in Git.
Advantages: clear history of environment changes, idempotency, standard rollbacks via Git.

10) Observability of CI/CD

DORA metrics: depletion rate, time from commit to production, failure rate, MTTR.
Telemetry: time of job queues, duration of stages, hit-rate of the cache, frequency of flaky tests.
Security logs: who initiated the release, which gates were passed, which exceptions were issued.

11) Access control and approvals

Branch protection and mandatory checks.
Environment-approvals: separate approvers lists on stage/prod.
JIT access for manual steps, session logging.

Separation of duties: different roles for "writes code," "approves," "releases."

12) Frequent errors (anti-patterns)

Long-lived cloud keys in repo secrets instead of OIDC roles.
Assembling different artifacts for stage and prod (violation of "build once").
'latest'tags and mutable images.
Publishing secrets in step logs (non-disabled masking).
One common public-runner for production deployments.
Lack of security "gates" (SAST/SCA/Policy) and post-deploy checks.

13) Implementation checklist (0-60 days)

0-15 days

Configure trunk-based, PR/MR rules, mandatory static checks.
Enable OIDC federation to the cloud; minimal'permissions'.
Post runners: public - for CI, private - for CD.

16-30 days

Add SBOM, image signature; Cluster - Signature Verification.
Enter canary/blue-green; auto-rollback by SLO.
Cache of dependencies and artifacts, pre-warm images.

31-60 days

Separate assembly and delivery (GitOps), policy-as-code gate.
Establish DORA metrics and alerts for the degradation of pipelines.
Template pipelines (reusable/child) for all services.

14) Practical reliability tips

Support small, fast pipelines (10-12 minutes before the PR signal).
Kill flaky tests: quarantine tags + parallel fix.
Do not mix CI artifacts and release artifacts; store metadata (commit, time, SBOM, signatures).
Give developers local scripts identical to pipeline steps (dev-prod parity).

15) Templates for reuse

15. 1 GitHub Actions - security reusable workflow (simplified)

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 - include template deploy (simplified)

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) Conclusion

GitHub Actions and GitLab CI provide mature mechanisms for a fast and secure code → prod loop. The key to success is standardization and security: OIDC instead of keys, signature and SBOM, quality gates, a single artifact with promotion, GitOps delivery and observability through DORA. Build pipelines as a product: Measure, simplify, speed up - and releases will become a chore, not an event.

Contact

Get in Touch

Reach out with any questions or support needs.We are always ready to help!

Telegram
@Gamble_GC
Start Integration

Email is required. Telegram or WhatsApp — optional.

Your Name optional
Email optional
Subject optional
Message optional
Telegram optional
@
If you include Telegram — we will reply there as well, in addition to Email.
WhatsApp optional
Format: +country code and number (e.g., +380XXXXXXXXX).

By clicking this button, you agree to data processing.