# GitLab CI/CD

GitLab CI/CD provides excellent Docker support with Docker-in-Docker (DinD) services, making it perfect for KushoAI test integration.

# Prerequisites

  • Docker-in-Docker: GitLab runners with Docker and DinD service support
  • Registry Access: Ability to pull from public ECR repositories
  • Variables Management: GitLab CI/CD Variables for configuration

# Docker Image

All execution uses the Kusho test runner Docker image:

public.ecr.aws/y5g4u6y7/kusho-test-runner:latest

# Setup Instructions

# 1. Create .gitlab-ci.yml

Create a .gitlab-ci.yml file in your repository root:

# 2. Basic Pipeline Configuration

stages:
  - test

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

kusho_tests:
  stage: test
  image: docker:24.0.0
  services:
    - docker:24.0.0-dind
  script:
    - docker run --rm \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="${ENVIRONMENT_ID}" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e CI_COMMIT_SHA="${CI_COMMIT_SHA}" \
        -e CI_COMMIT_MESSAGE="${CI_COMMIT_MESSAGE}" \
        -e TEST_SUITE_UUID="${TEST_SUITE_UUID}" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

# 3. Configure GitLab CI/CD Variables

Navigate to your GitLab project → Settings → CI/CD → Variables

# Protected Variables (Sensitive Data)

Variable Name Value Protected Masked
KUSHO_API_KEY Your Kusho API key

# Regular Variables (Configuration)

Variable Name Value Example
ENVIRONMENT_ID Target environment ID 2
TEST_SUITE_UUID Comma-separated UUIDs uuid1,uuid2
KUSHO_BASE_URL Base URL (optional) https://be.kusho.ai

# Execution Methods

# 1. Execute by Test Suite UUID

test_by_uuid:
  stage: test
  image: docker:24.0.0
  services:
    - docker:24.0.0-dind
  script:
    - docker run --rm \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="${ENVIRONMENT_ID}" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e CI_COMMIT_SHA="${CI_COMMIT_SHA}" \
        -e CI_COMMIT_MESSAGE="${CI_COMMIT_MESSAGE}" \
        -e TEST_SUITE_UUID="${TEST_SUITE_UUID}" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest

# 2. Execute by Group ID

test_by_group:
  stage: test
  image: docker:24.0.0
  services:
    - docker:24.0.0-dind
  script:
    - docker run --rm \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="${ENVIRONMENT_ID}" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e CI_COMMIT_SHA="${CI_COMMIT_SHA}" \
        -e CI_COMMIT_MESSAGE="${CI_COMMIT_MESSAGE}" \
        -e GROUP_ID="${GROUP_ID}" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest

# 3. Execute by Tags

test_by_tags:
  stage: test
  image: docker:24.0.0
  services:
    - docker:24.0.0-dind
  script:
    - docker run --rm \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="${ENVIRONMENT_ID}" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e CI_COMMIT_SHA="${CI_COMMIT_SHA}" \
        -e CI_COMMIT_MESSAGE="${CI_COMMIT_MESSAGE}" \
        -e TAGS="${TEST_TAGS}" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest

# 4. Execute E2E Workflows

test_e2e:
  stage: test
  image: docker:24.0.0
  services:
    - docker:24.0.0-dind
  script:
    - docker run --rm \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="${ENVIRONMENT_ID}" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e CI_COMMIT_SHA="${CI_COMMIT_SHA}" \
        -e CI_COMMIT_MESSAGE="${CI_COMMIT_MESSAGE}" \
        -e E2E_TEST_SUITE_UUID="${E2E_TEST_SUITE_UUID}" \
        -e EXECUTION_PROFILE_UUID="${EXECUTION_PROFILE_UUID}" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest

# Complete Pipeline Examples

# Multi-Stage Testing Pipeline

stages:
  - smoke
  - integration
  - e2e

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

.kusho_test_template: &kusho_test
  image: docker:24.0.0
  services:
    - docker:24.0.0-dind
  before_script:
    - docker info

smoke_tests:
  <<: *kusho_test
  stage: smoke
  script:
    - docker run --rm \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="${ENVIRONMENT_ID}" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e CI_COMMIT_SHA="${CI_COMMIT_SHA}" \
        -e CI_COMMIT_MESSAGE="${CI_COMMIT_MESSAGE}" \
        -e TAGS="smoke" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

integration_tests:
  <<: *kusho_test
  stage: integration
  script:
    - docker run --rm \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="${ENVIRONMENT_ID}" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e CI_COMMIT_SHA="${CI_COMMIT_SHA}" \
        -e CI_COMMIT_MESSAGE="${CI_COMMIT_MESSAGE}" \
        -e TAGS="integration" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
    - if: $CI_COMMIT_BRANCH == "develop"

e2e_tests:
  <<: *kusho_test
  stage: e2e
  script:
    - docker run --rm \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="${ENVIRONMENT_ID}" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e CI_COMMIT_SHA="${CI_COMMIT_SHA}" \
        -e CI_COMMIT_MESSAGE="${CI_COMMIT_MESSAGE}" \
        -e E2E_TEST_SUITE_UUID="${E2E_TEST_SUITE_UUID}" \
        -e EXECUTION_PROFILE_UUID="${EXECUTION_PROFILE_UUID}" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  when: manual
  allow_failure: true

# Multi-Environment Pipeline

stages:
  - test-staging
  - test-production

variables:
  DOCKER_DRIVER: overlay2

.test_template: &test_template
  image: docker:24.0.0
  services:
    - docker:24.0.0-dind

test_staging:
  <<: *test_template
  stage: test-staging
  script:
    - docker run --rm \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="2" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e CI_COMMIT_SHA="${CI_COMMIT_SHA}" \
        -e CI_COMMIT_MESSAGE="${CI_COMMIT_MESSAGE}" \
        -e TAGS="smoke,regression" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"

test_production:
  <<: *test_template
  stage: test-production
  script:
    - docker run --rm \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="1" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e CI_COMMIT_SHA="${CI_COMMIT_SHA}" \
        -e CI_COMMIT_MESSAGE="${CI_COMMIT_MESSAGE}" \
        -e TAGS="smoke" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  when: manual

# GitLab CI/CD Features

# Built-in Environment Variables

GitLab automatically provides commit information:

  • $CI_COMMIT_SHA - Full commit SHA
  • $CI_COMMIT_MESSAGE - Commit message
  • $CI_COMMIT_BRANCH - Current branch name
  • $CI_PIPELINE_SOURCE - Pipeline trigger source

# Rules for Conditional Execution

rules:
  - if: $CI_PIPELINE_SOURCE == "push"
  - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  - if: $CI_COMMIT_BRANCH == "main"
  - if: $CI_COMMIT_BRANCH =~ /^feature\/.*/

# Parallel Jobs

test_api_suite_1:
  extends: .kusho_test_template
  variables:
    TEST_SUITE_UUID: "uuid1,uuid2"

test_api_suite_2:
  extends: .kusho_test_template
  variables:
    TEST_SUITE_UUID: "uuid3,uuid4"

# Artifacts and Reports

kusho_tests:
  stage: test
  script:
    - docker run --rm \
        -v $(pwd)/results:/results \
        -e BASE_URL="${KUSHO_BASE_URL:-https://be.kusho.ai}" \
        -e ENVIRONMENT_ID="${ENVIRONMENT_ID}" \
        -e API_KEY="${KUSHO_API_KEY}" \
        -e TEST_SUITE_UUID="${TEST_SUITE_UUID}" \
        public.ecr.aws/y5g4u6y7/kusho-test-runner:latest
  artifacts:
    when: always
    expire_in: 1 week
    reports:
      junit: results/junit.xml
    paths:
      - results/

# GitLab-Specific Configurations

# Using GitLab Container Registry

If you want to cache the Docker image in your GitLab container registry:

pull_and_cache:
  stage: .pre
  image: docker:24.0.0
  services:
    - docker:24.0.0-dind
  script:
    - docker pull public.ecr.aws/y5g4u6y7/kusho-test-runner:latest
    - docker tag public.ecr.aws/y5g4u6y7/kusho-test-runner:latest $CI_REGISTRY_IMAGE/kusho-test-runner:latest
    - docker push $CI_REGISTRY_IMAGE/kusho-test-runner:latest
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"

# Environment-Specific Variables

Use GitLab environments for different deployment stages:

test_staging:
  stage: test
  environment:
    name: staging
  variables:
    ENVIRONMENT_ID: "2"
  script:
    - docker run --rm \
        -e ENVIRONMENT_ID="${ENVIRONMENT_ID}" \
        # ... other variables

# Integration with GitLab Issues

create_issue_on_failure:
  stage: .post
  image: alpine:latest
  script:
    - apk add --no-cache curl
    - |
      curl --request POST \
        --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \
        --header "Content-Type: application/json" \
        --data '{"title":"Test Failure in Pipeline","description":"Tests failed in pipeline '${CI_PIPELINE_ID}'"}' \
        "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/issues"
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
      when: on_failure

# Best Practices

# Security

  • Use protected and masked variables for sensitive data
  • Implement proper branch protection rules
  • Use GitLab CI/CD security scanning features

# Performance

  • Use YAML anchors to reduce duplication
  • Implement caching strategies for Docker layers
  • Use parallel jobs for independent test suites

# Organization

  • Use includes to modularize your pipeline configuration
  • Implement consistent naming conventions
  • Use extends for job templates

# Monitoring

  • Set up GitLab notifications for pipeline failures
  • Use GitLab's pipeline analytics
  • Implement custom metrics collection

# Troubleshooting

# Common Issues

  1. Docker-in-Docker Issues

    variables:
      DOCKER_TLS_CERTDIR: "/certs"
      DOCKER_DRIVER: overlay2
  2. Registry Access Problems

    • Ensure runner has internet access
    • Check DNS resolution for ECR registry
  3. Variable Issues

    • Verify variable names and values in project settings
    • Check variable scope (project vs group vs instance)

# Debug Mode

Enable debug logging:

variables:
  CI_DEBUG_TRACE: "true"

# Service Health Checks

before_script:
  - docker info
  - docker version
  - echo "Docker service is ready"

# Integration Examples

# Slack Notifications

notify_slack:
  stage: .post
  image: alpine:latest
  script:
    - apk add --no-cache curl
    - |
      curl -X POST -H 'Content-type: application/json' \
        --data '{"text":"Pipeline '${CI_PIPELINE_ID}' completed with status: '${CI_JOB_STATUS}'"}' \
        ${SLACK_WEBHOOK_URL}
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
      when: always

# Jira Integration

update_jira:
  stage: .post
  image: alpine:latest
  script:
    - apk add --no-cache curl
    - |
      curl -u ${JIRA_USER}:${JIRA_TOKEN} \
        -X POST \
        -H "Content-Type: application/json" \
        -d '{"body":"Pipeline completed for commit '${CI_COMMIT_SHA}'"}' \
        "${JIRA_URL}/rest/api/2/issue/${JIRA_ISSUE}/comment"
  rules:
    - if: $CI_COMMIT_MESSAGE =~ /JIRA-\d+/