Перейти к содержанию

Пример готового .gitlab-ci.yml


Структура пайплайна

Includes

Подключаем шаблоны из generic/common-ci:

include:
  - project: 'generic/common-ci'
    file: '/common-security-scan.yaml'
  - project: 'generic/common-ci'
    file: '/universal-pipeline.yaml'
    ref: apps-business

Примечание: ref: apps-business — ветка с актуальной версией шаблона. После стабилизации можно убрать.

Глобальные переменные

variables:
  SERVICE_NAME: bi-backend
  DOCKERFILE_PATH: ./docker/Dockerfile
  BUILD_ARGS: ""
  CI_TRIGGER_SOURCE: app
  • SERVICE_NAME — имя сервиса, используется для RELEASE_NAME и CHART_NAME
  • DOCKERFILE_PATH — путь к Dockerfile
  • BUILD_ARGS — дополнительные аргументы для docker build
  • CI_TRIGGER_SOURCE — источник триггера (app / infra)

Workflow.rules и переменные

Workflow определяет переменные для каждой ветки/тега:

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

    # Stage environment
    - if: '$CI_COMMIT_BRANCH == "stage"'
      variables:
        STAND: stage
        NAMESPACE: planning
        RELEASE_NAME: ${SERVICE_NAME}
        CHART_NAME: ${SERVICE_NAME}
        CHART_VERSION: "0.0.1-stage"
        K8S_HUSTLER_BRANCH: universal-chart-stage
        HELM_SET_ARGS: >-
          --set universal-chart.services.main.image.name.stage=${IMAGE_NAME}
          --set universal-chart.global.env=stage
          --set universal-chart.services.main.commitSha=${CI_COMMIT_SHA}
          --set universal-chart.services.main.gitlabUri=${CI_PROJECT_URL}
          --set universal-chart.services.main.gitlabJobUrl=${CI_JOB_URL}
          --set universal-chart.services.main.owner=${CI_PROJECT_NAMESPACE}

    # Preprod environment
    - if: '$CI_COMMIT_BRANCH == "master"'
      variables:
        STAND: preprod
        NAMESPACE: bi-preprod
        RELEASE_NAME: ${SERVICE_NAME}
        CHART_NAME: ${SERVICE_NAME}
        CHART_VERSION: "0.0.1-preprod"
        K8S_HUSTLER_BRANCH: universal-chart-preprod
        HELM_SET_ARGS: >-
          --set universal-chart.services.main.image.name.preprod=${IMAGE_NAME}
          --set universal-chart.global.env=preprod
          --set universal-chart.services.main.commitSha=${CI_COMMIT_SHA}
          --set universal-chart.services.main.gitlabUri=${CI_PROJECT_URL}
          --set universal-chart.services.main.gitlabJobUrl=${CI_JOB_URL}
          --set universal-chart.services.main.owner=${CI_PROJECT_NAMESPACE}

    # Production environment
    - if: '$CI_COMMIT_TAG'
      variables:
        STAND: production
        NAMESPACE: bi-prod
        RELEASE_NAME: ${SERVICE_NAME}
        CHART_NAME: ${SERVICE_NAME}
        CHART_VERSION: "0.0.1-prod"
        K8S_HUSTLER_BRANCH: universal-chart-production
        HELM_SET_ARGS: >-
          --set universal-chart.services.main.image.name.production=${IMAGE_NAME}
          --set universal-chart.global.env=production
          --set universal-chart.services.main.commitSha=${CI_COMMIT_SHA}
          --set universal-chart.services.main.gitlabUri=${CI_PROJECT_URL}
          --set universal-chart.services.main.gitlabJobUrl=${CI_JOB_URL}
          --set universal-chart.services.main.owner=${CI_PROJECT_NAMESPACE}
    - when: never

Ключевые моменты

  1. Путь к образу: universal-chart.services.<service>.image.name.<env>
  2. Для backend: universal-chart.services.main.image.name.stage
  3. Для frontend: universal-chart.services.frontend.image.name.stage

  4. Метаданные: передаются для каждого сервиса

  5. commitSha — SHA коммита
  6. gitlabUri — URL репозитория
  7. gitlabJobUrl — URL джобы
  8. owner — namespace проекта

  9. global.env: обязательно устанавливать для выбора значений через pluckEnv


Кастомные джобы

После includes можно добавить свои джобы:

# =============================================================================
# LINT & TESTS AND OTHER CUSTOM JOBS
# =============================================================================

lint:
  stage: lint
  image: ghcr.io/astral-sh/uv:0.7.3-python3.13-bookworm-slim
  script:
    - uv sync --locked
    - uv run ruff check src
    - uv run ruff format src --check
  rules:
    - if: '$CI_COMMIT_BRANCH'
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

typecheck:
  stage: lint
  image: ghcr.io/astral-sh/uv:0.7.3-python3.13-bookworm-slim
  script:
    - uv sync --locked
    - uv run mypy src
  rules:
    - if: '$CI_COMMIT_BRANCH'
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
  allow_failure: true

Полный пример для backend

include:
  - project: 'generic/common-ci'
    file: '/common-security-scan.yaml'
  - project: 'generic/common-ci'
    file: '/universal-pipeline.yaml'
    ref: apps-business

variables:
  SERVICE_NAME: bi-backend
  DOCKERFILE_PATH: ./docker/Dockerfile
  BUILD_ARGS: ""
  CI_TRIGGER_SOURCE: app

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

    - if: '$CI_COMMIT_BRANCH == "stage"'
      variables:
        STAND: stage
        NAMESPACE: planning
        RELEASE_NAME: ${SERVICE_NAME}
        CHART_NAME: ${SERVICE_NAME}
        CHART_VERSION: "0.0.1-stage"
        K8S_HUSTLER_BRANCH: universal-chart-stage
        HELM_SET_ARGS: >-
          --set universal-chart.services.main.image.name.stage=${IMAGE_NAME}
          --set universal-chart.global.env=stage
          --set universal-chart.services.main.commitSha=${CI_COMMIT_SHA}
          --set universal-chart.services.main.gitlabUri=${CI_PROJECT_URL}
          --set universal-chart.services.main.gitlabJobUrl=${CI_JOB_URL}
          --set universal-chart.services.main.owner=${CI_PROJECT_NAMESPACE}

    - if: '$CI_COMMIT_BRANCH == "master"'
      variables:
        STAND: preprod
        NAMESPACE: bi-preprod
        RELEASE_NAME: ${SERVICE_NAME}
        CHART_NAME: ${SERVICE_NAME}
        CHART_VERSION: "0.0.1-preprod"
        K8S_HUSTLER_BRANCH: universal-chart-preprod
        HELM_SET_ARGS: >-
          --set universal-chart.services.main.image.name.preprod=${IMAGE_NAME}
          --set universal-chart.global.env=preprod
          --set universal-chart.services.main.commitSha=${CI_COMMIT_SHA}
          --set universal-chart.services.main.gitlabUri=${CI_PROJECT_URL}
          --set universal-chart.services.main.gitlabJobUrl=${CI_JOB_URL}
          --set universal-chart.services.main.owner=${CI_PROJECT_NAMESPACE}

    - if: '$CI_COMMIT_TAG'
      variables:
        STAND: production
        NAMESPACE: bi-prod
        RELEASE_NAME: ${SERVICE_NAME}
        CHART_NAME: ${SERVICE_NAME}
        CHART_VERSION: "0.0.1-prod"
        K8S_HUSTLER_BRANCH: universal-chart-production
        HELM_SET_ARGS: >-
          --set universal-chart.services.main.image.name.production=${IMAGE_NAME}
          --set universal-chart.global.env=production
          --set universal-chart.services.main.commitSha=${CI_COMMIT_SHA}
          --set universal-chart.services.main.gitlabUri=${CI_PROJECT_URL}
          --set universal-chart.services.main.gitlabJobUrl=${CI_JOB_URL}
          --set universal-chart.services.main.owner=${CI_PROJECT_NAMESPACE}
    - when: never

lint:
  stage: lint
  image: ghcr.io/astral-sh/uv:0.7.3-python3.13-bookworm-slim
  script:
    - uv sync --locked
    - uv run ruff check src
    - uv run ruff format src --check
  rules:
    - if: '$CI_COMMIT_BRANCH'
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

Полный пример для frontend

include:
  - project: 'generic/common-ci'
    file: '/common-security-scan.yaml'
  - project: 'generic/common-ci'
    file: '/universal-pipeline.yaml'
    ref: apps-business

variables:
  SERVICE_NAME: bi-frontend
  DOCKERFILE_PATH: ./Dockerfile
  BUILD_ARGS: ""
  CI_TRIGGER_SOURCE: app

workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

    - if: '$CI_COMMIT_BRANCH == "stage"'
      variables:
        STAND: stage
        NAMESPACE: planning
        RELEASE_NAME: ${SERVICE_NAME}
        CHART_NAME: ${SERVICE_NAME}
        CHART_VERSION: "0.0.1-stage"
        K8S_HUSTLER_BRANCH: universal-chart-stage
        BUILD_ARGS: "--build-arg ENDPOINT=stage --build-arg NPM_NEXUS_TOKEN=${NPM_NEXUS_TOKEN}"
        HELM_SET_ARGS: >-
          --set universal-chart.services.frontend.image.name.stage=${IMAGE_NAME}
          --set universal-chart.global.env=stage
          --set universal-chart.services.frontend.commitSha=${CI_COMMIT_SHA}
          --set universal-chart.services.frontend.gitlabUri=${CI_PROJECT_URL}
          --set universal-chart.services.frontend.gitlabJobUrl=${CI_JOB_URL}
          --set universal-chart.services.frontend.owner=${CI_PROJECT_NAMESPACE}

    - if: '$CI_COMMIT_BRANCH == "master"'
      variables:
        STAND: preprod
        NAMESPACE: bi-preprod
        RELEASE_NAME: ${SERVICE_NAME}
        CHART_NAME: ${SERVICE_NAME}
        CHART_VERSION: "0.0.1-preprod"
        K8S_HUSTLER_BRANCH: universal-chart-preprod
        BUILD_ARGS: "--build-arg ENDPOINT=preprod --build-arg NPM_NEXUS_TOKEN=${NPM_NEXUS_TOKEN}"
        HELM_SET_ARGS: >-
          --set universal-chart.services.frontend.image.name.preprod=${IMAGE_NAME}
          --set universal-chart.global.env=preprod
          --set universal-chart.services.frontend.commitSha=${CI_COMMIT_SHA}
          --set universal-chart.services.frontend.gitlabUri=${CI_PROJECT_URL}
          --set universal-chart.services.frontend.gitlabJobUrl=${CI_JOB_URL}
          --set universal-chart.services.frontend.owner=${CI_PROJECT_NAMESPACE}

    - if: '$CI_COMMIT_TAG'
      variables:
        STAND: production
        NAMESPACE: bi-prod
        RELEASE_NAME: ${SERVICE_NAME}
        CHART_NAME: ${SERVICE_NAME}
        CHART_VERSION: "0.0.1-prod"
        K8S_HUSTLER_BRANCH: universal-chart-production
        BUILD_ARGS: "--build-arg ENDPOINT=prod --build-arg NPM_NEXUS_TOKEN=${NPM_NEXUS_TOKEN}"
        HELM_SET_ARGS: >-
          --set universal-chart.services.frontend.image.name.production=${IMAGE_NAME}
          --set universal-chart.global.env=production
          --set universal-chart.services.frontend.commitSha=${CI_COMMIT_SHA}
          --set universal-chart.services.frontend.gitlabUri=${CI_PROJECT_URL}
          --set universal-chart.services.frontend.gitlabJobUrl=${CI_JOB_URL}
          --set universal-chart.services.frontend.owner=${CI_PROJECT_NAMESPACE}
    - when: never

Обратите внимание: для frontend используется services.frontend, а не services.main.