# GitLab CI/CD Configuration for num-valid
# This configuration runs tests with all feature and build mode combinations,
# verifies test coverage and updates badges

# Defines Docker images and pipeline stages
stages:
  - build
  - test
  - coverage
  - badges
  - security

# Global variables
variables:
  CARGO_HOME: $CI_PROJECT_DIR/.cargo
  CARGO_TARGET_DIR: $CI_PROJECT_DIR/target
  RUST_BACKTRACE: "1"
  SECRET_DETECTION_ENABLED: 'true'

# Cache to speed up builds
cache:
  key:
    files:
      - Cargo.lock
      - Cargo.toml
  paths:
    - .cargo/
    - target/

# Base template for Rust jobs
.rust_template: &rust_template
  image: rustlang/rust:nightly
  before_script:
    - apt-get update && apt-get install -y libgmp-dev libmpfr-dev libmpc-dev
    - rustc --version
    - cargo --version
    - cargo fetch

# ================================
# BUILD PHASE - Verify compilation
# ================================

build_without_rug:
  <<: *rust_template
  stage: build
  script:
    - echo "Building without rug feature..."
    - cargo check --all-targets
    - cargo check --all-targets --release
  artifacts:
    reports:
      junit: test-results.xml
    expire_in: 1 hour
  only:
    - master

build_with_rug:
  <<: *rust_template
  stage: build
  script:
    - echo "Building with rug feature..."
    - cargo check --all-targets --features rug
    - cargo check --all-targets --features rug --release
  artifacts:
    reports:
      junit: test-results.xml
    expire_in: 1 hour
  only:
    - master

# ================================
# TEST PHASE - All combinations
# ================================

# Tests without "rug" feature in Debug
test_debug_no_rug:
  <<: *rust_template
  stage: test
  needs: ["build_without_rug"]
  script:
    - echo "Running tests in Debug mode without rug feature..."
    - cargo test --all-targets --verbose
  artifacts:
    reports:
      junit: test-results.xml
    expire_in: 1 week
  only:
    - master

# Tests without "rug" feature in Release
test_release_no_rug:
  <<: *rust_template
  stage: test
  needs: ["build_without_rug"]
  script:
    - echo "Running tests in Release mode without rug feature..."
    - cargo test --all-targets --release --verbose
  artifacts:
    reports:
      junit: test-results.xml
    expire_in: 1 week
  only:
    - master

# Tests with "rug" feature in Debug
test_debug_with_rug:
  <<: *rust_template
  stage: test
  needs: ["build_with_rug"]
  script:
    - echo "Running tests in Debug mode with rug feature..."
    - cargo test --all-targets --features rug --verbose
  artifacts:
    reports:
      junit: test-results.xml
    expire_in: 1 week
  only:
    - master

# Tests with "rug" feature in Release
test_release_with_rug:
  <<: *rust_template
  stage: test
  needs: ["build_with_rug"]
  script:
    - echo "Running tests in Release mode with rug feature..."
    - cargo test --all-targets --features rug --release --verbose
  artifacts:
    reports:
      junit: test-results.xml
    expire_in: 1 week
  only:
    - master

# Benchmark tests (without running them, only verify compilation)
test_benchmarks:
  <<: *rust_template
  stage: test
  script:
    - echo "Checking benchmarks compilation..."
    - cargo check --benches
    - cargo check --benches --features rug
  allow_failure: true
  only:
    - master

# ================================
# COVERAGE PHASE - Test coverage
# ================================

coverage:
  <<: *rust_template
  stage: coverage
  needs: 
    - test_debug_no_rug
    - test_release_no_rug
    - test_debug_with_rug
    - test_release_with_rug
  script:
    - cargo install cargo-tarpaulin
    - echo "Running coverage analysis..."
    - |
      COVERAGE_LINE=$(cargo tarpaulin --skip-clean --engine llvm --config tarpaulin.toml --exclude-files benches/* --out Xml Html stdout --output-dir coverage)
      echo "$COVERAGE_LINE"
      COVERAGE=$(echo "$COVERAGE_LINE" | awk -F'%' '/coverage/ {print $1}' | tail -n 1)
      echo "Coverage: $COVERAGE%"
      echo "COVERAGE=$COVERAGE" > coverage/coverage.env   
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura.xml
    paths:
      - coverage/
    expire_in: 1 week
  coverage: '/Coverage: (\d+\.?\d*)%/'
  only:
    - master

# ================================
# BADGES PHASE - Update badges
# ================================

# Job to generate pipeline badges
update_badges:
  stage: badges
  image: alpine:latest
  needs: 
    - coverage
  before_script:
    - apk add --no-cache curl jq
  script:
    - source coverage/coverage.env || true
    - echo "Updating badges..."
    - 'if [ "$CI_PIPELINE_STATUS" = "success" ]; then PIPELINE_BADGE_COLOR="brightgreen"; PIPELINE_BADGE_MESSAGE="passing"; else PIPELINE_BADGE_COLOR="red"; PIPELINE_BADGE_MESSAGE="failing"; fi'
    - 'if [ -n "$COVERAGE" ]; then if (( $(echo "$COVERAGE >= 90" | bc -l) )); then COVERAGE_BADGE_COLOR="brightgreen"; elif (( $(echo "$COVERAGE >= 75" | bc -l) )); then COVERAGE_BADGE_COLOR="yellow"; else COVERAGE_BADGE_COLOR="red"; fi; COVERAGE_BADGE_MESSAGE="${COVERAGE}%"; else COVERAGE_BADGE_COLOR="lightgrey"; COVERAGE_BADGE_MESSAGE="unknown"; fi'
    - echo "Pipeline Status Badge URL:"
    - echo "https://img.shields.io/badge/pipeline-${PIPELINE_BADGE_MESSAGE}-${PIPELINE_BADGE_COLOR}.svg"
    - echo ""
    - echo "Coverage Badge URL:"
    - echo "https://img.shields.io/badge/coverage-${COVERAGE_BADGE_MESSAGE}-${COVERAGE_BADGE_COLOR}.svg"
    - echo ""
    - echo "GitLab Pipeline Badge URL:"
    - echo "${CI_PROJECT_URL}/badges/${CI_DEFAULT_BRANCH}/pipeline.svg"
    - echo ""
    - echo "GitLab Coverage Badge URL (if coverage reporting is enabled):"
    - echo "${CI_PROJECT_URL}/badges/${CI_DEFAULT_BRANCH}/coverage.svg"
    
  artifacts:
    expire_in: 1 week
  only:
    - master

# ================================
# ADDITIONAL JOBS
# ================================

# Code formatting verification
fmt_check:
  <<: *rust_template
  stage: test
  script:
    - rustup component add rustfmt
    - echo "Checking code formatting..."
    - cargo fmt --all -- --check
  allow_failure: true

# Clippy verification
clippy_check:
  <<: *rust_template
  stage: test
  script:
    - rustup component add clippy
    - echo "Running clippy lints..."
    - cargo clippy --all-targets -- -D warnings
    - cargo clippy --all-targets --features rug -- -D warnings
  allow_failure: true

# Documentation verification
doc_check:
  <<: *rust_template
  stage: test
  script:
    - echo "Checking documentation..."
    - cargo doc --no-deps --document-private-items
    - cargo doc --no-deps --document-private-items --features rug
  artifacts:
    paths:
      - target/doc/
    expire_in: 1 week
  allow_failure: true

# Job for documentation deployment (optional)
pages:
  stage: badges
  needs: ["doc_check"]
  script:
    - mkdir public
    - cp -r target/doc/* public/
  artifacts:
    paths:
      - public
  only:
    - master
  when: manual

# ================================
# SPECIAL CONFIGURATIONS
# ================================

# Job that runs only on schedules (for comprehensive nightly tests)
nightly_full_test:
  <<: *rust_template
  stage: test
  script:
    - echo "Running comprehensive nightly tests..."
    - cargo test --all-targets --verbose
    - cargo test --all-targets --features rug --verbose --release
    - timeout 300 cargo bench --features rug || echo "Benchmarks completed or timed out"
  only:
    - schedules
  allow_failure: true

# ================================
# SECURITY
# ================================

# Job to verify security dependencies
security_audit:
  <<: *rust_template
  stage: security
  before_script:
    - cargo install cargo-audit
  script:
    - echo "Running security audit..."
    - cargo audit
  allow_failure: true
  only:
    - schedules
    - master

# Secret detection (kept from original file)
secret_detection:
  stage: security

# Include security templates
include:
- template: Security/Secret-Detection.gitlab-ci.yml
