Skip to content

CI/CD Integration

Hive integrates with GitLab CI through dynamic pipeline generation.

How it works

graph LR
    A[git push] --> B[generate-pipeline]
    B -->|hive ci --global| C[child-pipeline.yml]
    C --> D[run-pipeline]
    D --> T[token]
    T --> E[init]
    E --> F[build]
    F --> G[test]
    G --> H[deploy]
  1. git push starts the main pipeline
  2. The generate stage calls hive ci --global — generates CI jobs from .hive.yml files
  3. The run stage launches the generated pipeline as a child pipeline
  4. Child pipeline: token → init → build → test → deploy for each service

Setup

.gitlab-ci.yml (repository root)

stages:
  - generate
  - run

generate-pipeline:
  stage: generate
  image: lab.xmonetize.net:5050/infrastructure/hive/hive-api/cli:latest
  script:
    - hive ci --global > child-pipeline.yml
  artifacts:
    paths:
      - child-pipeline.yml

run-pipeline:
  stage: run
  trigger:
    include:
      - artifact: child-pipeline.yml
        job: generate-pipeline
    strategy: depend

That's it. Set up once — the pipeline updates automatically when you add or remove services.

What gets generated

token

Creates the project's gitlab-deploy-token if it has none (hive token). A separate stage, so that the init job already gets the token in CI_DEPLOY_USER/CI_DEPLOY_PASSWORD.

init

Registers the repository in ArgoCD with the project's deploy token. One job per pipeline, not per-service.

  • Image: lab.xmonetize.net:5050/infrastructure/hive/hive-api/cli:latest
  • Idempotent: re-registering updates the credentials; no new tokens are created
  • Runs: when the parent pipeline triggers the child (branch rules live in the parent)

Three jobs are created for each service:

build-{name}

Builds a container using Cloud Native Buildpacks.

  • Image: lab.xmonetize.net:5050/infrastructure/hive/hive-api/cli:latest
  • Services: docker:27-dind (Docker-in-Docker)
  • Runs: only on default branch

test-{name}

Starts the container and checks the health endpoint.

  • Depends on: build-{name}
  • Services: docker:27-dind
  • Artifacts: JUnit XML report (hive-test-report.xml)

deploy-{name}

Deploys via Hive API → ArgoCD → Knative.

  • Depends on: test-{name}
  • Runs: only on default branch

CI variables

These variables must be configured in GitLab CI/CD Settings:

Variable Description Where to configure
HIVE_API_URL Hive API URL CI/CD Variables (group or project)
HIVE_API_TOKEN Bearer token CI/CD Variables (masked)
ARGOCD_URL ArgoCD URL (for bootstrap) CI/CD Variables, scoped per environment
ARGOCD_TOKEN ArgoCD token (for bootstrap) CI/CD Variables, scoped per environment
CI_REGISTRY_IMAGE Auto — registry address Automatically by GitLab
CI_PIPELINE_ID Auto — image tag Automatically by GitLab

Secrets

HIVE_API_TOKEN should be masked and protected. Never commit tokens to the repository.

Multi-service pipeline

For a multi-service repository, parallel chains are generated:

         ┌→ build-frontend  → test-frontend  → deploy-frontend
init ────┼→ build-backend   → test-backend   → deploy-backend
         └→ build-worker    → test-worker    → deploy-worker

Each service is built and deployed independently. CI_REGISTRY_IMAGE gets a /{name} suffix.

Services with type: cronjobs skip the test stage (no HTTP port to probe):

         ┌→ build-api        → test-api        → deploy-api
init ────┼→ build-frontend   → test-frontend   → deploy-frontend
         └→ build-workers    ──────────────────→ deploy-workers  (cronjobs)

JUnit reports

The test stage generates JUnit XML. GitLab automatically shows test results in the Merge Request:

artifacts:
  when: always
  reports:
    junit: hive-test-report.xml

If a test fails, the report will contain container logs — this helps quickly find the cause.

Branch filtering

Branch filtering is managed in the parent .gitlab-ci.yml via rules:, not in the generated child pipeline. This means you control which branches trigger builds and deploys in one place:

# .gitlab-ci.yml (parent pipeline)
generate-pipeline-staging:
  # ...
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

run-pipeline-staging:
  # ...
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

To enable deploys from feature branches, adjust the rules: in your .gitlab-ci.yml.

Environments

The list of environments and what differs between them is on the Environments page. hive ci --global -E <name> reads cli/environments.yaml and injects the environment's variables into the generated pipeline: the init job gets HIVE_API_URL and HIVE_ENVIRONMENT, the deploy jobs get HIVE_API_URL, HIVE_DOMAIN and HIVE_ENVIRONMENT. An unknown name is an error.

This solves the problem of GitLab environment-scoped variables not propagating to child pipelines.

Multi-environment .gitlab-ci.yml

Staging deploys automatically; each production environment waits for a manual start. Keep only the environments the service needs.

stages:
  - generate
  - staging
  - production
  - envik

generate-pipeline-staging:
  stage: generate
  image: lab.xmonetize.net:5050/infrastructure/hive/hive-api/cli:latest
  script:
    - hive ci --global -E staging > child-pipeline-staging.yml
  artifacts:
    paths:
      - child-pipeline-staging.yml
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

generate-pipeline-production:
  stage: generate
  image: lab.xmonetize.net:5050/infrastructure/hive/hive-api/cli:latest
  script:
    - hive ci --global -E production > child-pipeline-production.yml
  artifacts:
    paths:
      - child-pipeline-production.yml
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

generate-pipeline-envik:
  stage: generate
  image: lab.xmonetize.net:5050/infrastructure/hive/hive-api/cli:latest
  script:
    - hive ci --global -E envik > child-pipeline-envik.yml
  artifacts:
    paths:
      - child-pipeline-envik.yml
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

run-pipeline-staging:
  stage: staging
  trigger:
    include:
      - artifact: child-pipeline-staging.yml
        job: generate-pipeline-staging
    strategy: depend
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

run-pipeline-production:
  stage: production
  trigger:
    include:
      - artifact: child-pipeline-production.yml
        job: generate-pipeline-production
    strategy: depend
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: manual

run-pipeline-envik:
  stage: envik
  trigger:
    include:
      - artifact: child-pipeline-envik.yml
        job: generate-pipeline-envik
    strategy: depend
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: manual