Ctrl K
ComunidadGuías…

docker-compose.test.yml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Docker Compose configuration for E2E Testing
# Supports Docker Compose profiles for selective test execution
#
# Usage:
#   docker compose -f docker-compose.test.yml --profile pypi up               # PyPI native client tests
#   docker compose -f docker-compose.test.yml --profile all up                # All native client tests
#
# Profiles:
#   pypi        - PyPI/pip tests (smoke)
#   npm         - NPM tests (smoke)
#   cargo       - Cargo/crates tests (smoke)
#   maven       - Maven tests
#   go          - Go modules tests
#   rpm         - RPM/dnf tests (requires gpg)
#   deb         - Debian/apt tests (requires gpg)
#   helm        - Helm chart tests
#   conda       - Conda package tests
#   docker      - Docker/OCI image tests
#   protobuf    - Protobuf/BSR Connect RPC tests
#   hex         - Hex/Elixir package tests
#   proxy       - Remote proxy + virtual repository tests
#   storage-gc  - Storage garbage collection tests
#   curation    - Curation policy E2E tests (RPM/DEB with mock upstream)
#   smoke       - Smoke tests only (pypi, npm, cargo)
#   all         - All native client tests

services:
  # ==========================================================================
  # INFRASTRUCTURE SERVICES (Always available)
  # ==========================================================================

  postgres:
    image: ghcr.io/artifact-keeper/ci-mirror/postgres:18-alpine
    container_name: e2e-test-db
    environment:
      POSTGRES_USER: registry
      POSTGRES_PASSWORD: registry
      POSTGRES_DB: artifact_registry
    tmpfs:
      - /var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U registry -d artifact_registry"]
      interval: 2s
      timeout: 5s
      retries: 10
    networks:
      - e2e-test-network

  backend:
    image: artifact-keeper-backend:test
    build:
      context: .
      dockerfile: docker/Dockerfile.backend
    container_name: e2e-test-backend
    depends_on:
      postgres:
        condition: service_healthy
    # THROWAWAY CREDENTIAL — NOT for deployment (#3490). Supplies ADMIN_PASSWORD
    # (and, for the test containers below, ADMIN_PASS). The value is defined
    # ONCE, in .env.test at the repository root, and nowhere else: a default
    # spelled into each of these services put ~60 copies of one password string
    # in the repository, which is indistinguishable from a leaked credential to
    # a secret scanner (#3938). This stack is torn down with `down -v` at the
    # end of every run and the value only has to be the one the test scripts log
    # in with; export AK_TEST_ADMIN_PASSWORD (e.g.
    # `export AK_TEST_ADMIN_PASSWORD=$(openssl rand -base64 24)`, which
    # scripts/run-e2e-tests.sh does for you) to override it for a run. Anyone
    # copying this file as a deployment starting point must set ADMIN_PASSWORD
    # from their own secret store — see the credential notes in the root
    # docker-compose.yml.
    env_file:
      - .env.test
    environment:
      DATABASE_URL: postgresql://registry:registry@postgres:5432/artifact_registry
      STORAGE_PATH: /data/storage
      BACKUP_PATH: /data/backups
      PLUGINS_DIR: /data/plugins
      JWT_SECRET: smoke-e2e-nonprod-violet-quartz-meadow-7391
      # E2E-ONLY SSRF relaxation (#3363). The cache-correctness, curation and
      # proxy profiles create `remote` repositories pointing at mock upstreams
      # that live on this compose network (`cache-mock-upstream:9101`,
      # `mock-upstream`). Those names resolve to the bridge network's RFC1918
      # addresses, which the outbound-URL guard added in #1832 rejects, so
      # `create_repo` returned HTTP 400 and the harnesses aborted in their
      # setup phase before reaching a single assertion.
      #
      # The narrower `AK_SSRF_ALLOW_PRIVATE_CIDRS` would be preferable, but
      # `e2e-test-network` is a plain bridge with no pinned subnet, so there is
      # no stable CIDR to name here. Loopback, link-local and cloud-metadata
      # addresses stay hard-blocked regardless of this toggle, and the backend
      # logs a startup warning when it is set — which is the point: it must
      # never be set anywhere but a throwaway test stack.
      UPSTREAM_ALLOW_PRIVATE_IPS: "true"
      RUST_LOG: info
      TRIVY_URL: http://trivy:8090
      HOST: 0.0.0.0
      PORT: 8080
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 5s
      timeout: 10s
      start_period: 30s
      retries: 10
    networks:
      - e2e-test-network

  trivy:
    image: ghcr.io/aquasecurity/trivy:0.76.0
    container_name: e2e-test-trivy
    command: ["server", "--listen", "0.0.0.0:8090"]
    # Air-gapped variant (#5287): add "--skip-db-update" once the cache volume
    # holds a DB; see the trivy service in docker-compose.yml.
    volumes:
      - trivy-cache:/root/.cache/trivy
    networks:
      - e2e-test-network

  # Bootstrap: create test repositories after backend is healthy
  setup:
    image: ghcr.io/artifact-keeper/ci-mirror/alpine:3.24
    container_name: e2e-test-setup
    depends_on:
      backend:
        condition: service_healthy
    volumes:
      - ./scripts/e2e-setup.sh:/setup.sh:ro
    command: ["sh", "/setup.sh"]
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
    healthcheck:
      test: ["CMD", "test", "-f", "/tmp/.setup-done"]
      interval: 2s
      timeout: 5s
      retries: 30
    networks:
      - e2e-test-network
    profiles: ["pypi", "npm", "cargo", "maven", "go", "rpm", "deb", "helm", "conda", "docker", "smoke", "all", "proxy", "docker-proxy", "terraform-mirror", "terraform-modules", "redteam", "tag-replication", "curation", "cache-correctness"]

  # PKI service: uses pre-generated files from .pki/ if available (CI), otherwise generates them (local)
  pki:
    image: ghcr.io/artifact-keeper/ci-mirror/alpine:3.24
    container_name: e2e-test-pki
    command: >
      sh -c "
        if [ -f /host-pki/ca.crt ] && [ -f /host-pki/server.crt ]; then
          echo 'Using pre-generated PKI files from host';
          cp -r /host-pki/* /pki/ 2>/dev/null || true;
          chmod 644 /pki/*.crt /pki/*.pub 2>/dev/null || true;
          chmod 600 /pki/*.key 2>/dev/null || true;
        else
          echo 'Generating PKI files...';
          apk add --no-cache openssl gnupg bash curl &&
          bash /scripts/pki/generate-certs.sh /pki &&
          bash /scripts/pki/generate-gpg.sh /pki;
        fi &&
        echo 'PKI setup complete' &&
        touch /pki/.ready &&
        tail -f /dev/null
      "
    volumes:
      - ./scripts/pki:/scripts/pki:ro
      - ./.pki:/host-pki:ro
      - pki-data:/pki
    healthcheck:
      test: ["CMD", "test", "-f", "/pki/.ready"]
      interval: 5s
      timeout: 5s
      retries: 20
    networks:
      - e2e-test-network
    profiles: ["pypi", "npm", "cargo", "maven", "go", "rpm", "deb", "helm", "conda", "docker", "smoke", "all", "proxy", "docker-proxy", "terraform-modules", "redteam", "tag-replication", "curation", "cache-correctness"]

  # ==========================================================================
  # SMOKE TEST SERVICES (pypi, npm, cargo)
  # ==========================================================================

  pypi-test:
    image: ghcr.io/artifact-keeper/ci-mirror/python:3.14-slim
    container_name: e2e-test-pypi
    depends_on:
      setup:
        condition: service_healthy
      pki:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
      CA_CERT: /pki/ca.crt
    volumes:
      - ./scripts/native-tests:/scripts:ro
      - ./.assets:/assets:ro
      - pki-data:/pki:ro
    command: ["bash", "/scripts/test-pypi.sh"]
    networks:
      - e2e-test-network
    profiles: ["pypi", "smoke", "all"]

  npm-test:
    image: ghcr.io/artifact-keeper/ci-mirror/node:26-slim
    container_name: e2e-test-npm
    depends_on:
      setup:
        condition: service_healthy
      pki:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
      CA_CERT: /pki/ca.crt
    volumes:
      - ./scripts/native-tests:/scripts:ro
      - ./.assets:/assets:ro
      - pki-data:/pki:ro
    command: ["bash", "/scripts/test-npm.sh"]
    networks:
      - e2e-test-network
    profiles: ["npm", "smoke", "all"]

  cargo-test:
    image: ghcr.io/artifact-keeper/ci-mirror/rust:1.98-slim
    container_name: e2e-test-cargo
    depends_on:
      setup:
        condition: service_healthy
      pki:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
      CA_CERT: /pki/ca.crt
    volumes:
      - ./scripts/native-tests:/scripts:ro
      - ./.assets:/assets:ro
      - pki-data:/pki:ro
    command: ["bash", "/scripts/test-cargo.sh"]
    networks:
      - e2e-test-network
    profiles: ["cargo", "smoke", "all"]

  # ==========================================================================
  # EXTENDED TEST SERVICES (Require specific profiles)
  # ==========================================================================

  maven-test:
    image: maven:3.9-eclipse-temurin-21
    container_name: e2e-test-maven
    depends_on:
      setup:
        condition: service_healthy
      pki:
        condition: service_healthy
    environment:
      REGISTRY_URL: http://backend:8080
      CA_CERT: /pki/ca.crt
    volumes:
      - ./scripts/native-tests:/scripts:ro
      - ./.assets:/assets:ro
      - pki-data:/pki:ro
      - maven-cache:/root/.m2
    command: ["bash", "/scripts/test-maven.sh"]
    networks:
      - e2e-test-network
    profiles: ["maven", "all"]

  go-test:
    image: golang:1.27-alpine
    container_name: e2e-test-go
    depends_on:
      setup:
        condition: service_healthy
      pki:
        condition: service_healthy
    environment:
      REGISTRY_URL: http://backend:8080
      GOPROXY: http://backend:8080/go/test-go
      CA_CERT: /pki/ca.crt
    volumes:
      - ./scripts/native-tests:/scripts:ro
      - ./.assets:/assets:ro
      - pki-data:/pki:ro
      - go-cache:/go/pkg
    command: ["sh", "-c", "apk add --no-cache bash curl >/dev/null 2>&1 && bash /scripts/test-go.sh"]
    networks:
      - e2e-test-network
    profiles: ["go", "all"]

  rpm-test:
    image: rockylinux/rockylinux:9-ubi-init
    container_name: e2e-test-rpm
    depends_on:
      setup:
        condition: service_healthy
      pki:
        condition: service_healthy
    environment:
      REGISTRY_URL: http://backend:8080
      CA_CERT: /pki/ca.crt
      GPG_KEY: /pki/gpg-signing.pub
    volumes:
      - ./scripts/native-tests:/scripts:ro
      - ./.assets:/assets:ro
      - pki-data:/pki:ro
    command: ["bash", "/scripts/test-rpm.sh"]
    networks:
      - e2e-test-network
    profiles: ["rpm", "all"]

  deb-test:
    image: debian:trixie-slim
    container_name: e2e-test-deb
    depends_on:
      setup:
        condition: service_healthy
      pki:
        condition: service_healthy
    environment:
      REGISTRY_URL: http://backend:8080
      CA_CERT: /pki/ca.crt
      GPG_KEY: /pki/gpg-signing.pub
    volumes:
      - ./scripts/native-tests:/scripts:ro
      - ./.assets:/assets:ro
      - pki-data:/pki:ro
    command: ["bash", "/scripts/test-deb.sh"]
    networks:
      - e2e-test-network
    profiles: ["deb", "all"]

  helm-test:
    image: alpine/helm:3.21
    container_name: e2e-test-helm
    depends_on:
      setup:
        condition: service_healthy
      pki:
        condition: service_healthy
    environment:
      REGISTRY_URL: http://backend:8080
      CA_CERT: /pki/ca.crt
    volumes:
      - ./scripts/native-tests:/scripts:ro
      - ./.assets:/assets:ro
      - pki-data:/pki:ro
    command: ["sh", "-c", "apk add --no-cache bash curl >/dev/null 2>&1 && bash /scripts/test-helm.sh"]
    networks:
      - e2e-test-network
    profiles: ["helm", "all"]

  conda-test:
    image: continuumio/miniconda3:latest
    container_name: e2e-test-conda
    depends_on:
      setup:
        condition: service_healthy
      pki:
        condition: service_healthy
    environment:
      REGISTRY_URL: http://backend:8080
      CA_CERT: /pki/ca.crt
    volumes:
      - ./scripts/native-tests:/scripts:ro
      - ./.assets:/assets:ro
      - pki-data:/pki:ro
    command: ["bash", "/scripts/test-conda.sh"]
    networks:
      - e2e-test-network
    profiles: ["conda", "all"]

  docker-test:
    image: docker:24-cli
    container_name: e2e-test-docker
    depends_on:
      setup:
        condition: service_healthy
      pki:
        condition: service_healthy
    environment:
      REGISTRY_URL: backend:8080
      CA_CERT: /pki/ca.crt
    volumes:
      - ./scripts/native-tests:/scripts:ro
      - ./.assets:/assets:ro
      - pki-data:/pki:ro
      - /var/run/docker.sock:/var/run/docker.sock
    command: ["sh", "-c", "apk add --no-cache bash curl jq >/dev/null 2>&1 && bash /scripts/test-docker.sh"]
    networks:
      - e2e-test-network
    profiles: ["docker", "all"]

  # ==========================================================================
  # PROTOBUF / BSR TESTS
  # ==========================================================================

  protobuf-test:
    image: docker.io/alpine:3.24
    container_name: e2e-test-protobuf
    depends_on:
      setup:
        condition: service_healthy
    environment:
      REGISTRY_URL: http://backend:8080
    volumes:
      - ./scripts/native-tests:/scripts:ro
    command: ["sh", "-c", "apk add --no-cache bash curl jq coreutils >/dev/null 2>&1 && bash /scripts/test-protobuf.sh"]
    networks:
      - e2e-test-network
    profiles: ["protobuf", "all"]

  hex-test:
    image: docker.io/alpine:3.24
    container_name: e2e-test-hex
    depends_on:
      setup:
        condition: service_healthy
    environment:
      REGISTRY_URL: http://backend:8080
      HEX_REPO_KEY: test-hex
    volumes:
      - ./scripts/native-tests:/scripts:ro
    command: ["sh", "-c", "apk add --no-cache bash curl tar jq coreutils >/dev/null 2>&1 && bash /scripts/test-hex.sh"]
    networks:
      - e2e-test-network
    profiles: ["hex", "all"]

  # ==========================================================================
  # TERRAFORM / OPENTOFU NETWORK MIRROR TESTS
  # ==========================================================================

  terraform-mirror-test:
    image: hashicorp/terraform:1.16.0
    container_name: e2e-test-terraform-mirror
    depends_on:
      setup:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
      TF_UPSTREAM_URL: https://registry.terraform.io
      TF_HOSTNAME: registry.terraform.io
      TF_NAMESPACE: hashicorp
      TF_TYPE: null
      TF_VERSION: 3.2.3
      TF_OS: linux
      TF_ARCH: amd64
      RUN_TERRAFORM_CLI: "1"
    volumes:
      - ./scripts/native-tests:/scripts:ro
    entrypoint: ["/bin/sh", "-c"]
    command: ["apk add --no-cache bash curl jq coreutils >/dev/null 2>&1 && bash /scripts/test-terraform-mirror.sh"]
    networks:
      - e2e-test-network
    profiles: ["terraform-mirror"]

  # ==========================================================================
  # TERRAFORM / OPENTOFU HOSTED MODULE INSTALL TESTS (#4590)
  # ==========================================================================

  terraform-modules-test:
    image: hashicorp/terraform:1.16.0
    container_name: e2e-test-terraform-modules
    depends_on:
      setup:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
      TF_CLI_BIN: terraform
      CADDY_BIN: caddy
      RUN_TF_CLI: "1"
    volumes:
      - ./scripts/native-tests:/scripts:ro
    entrypoint: ["/bin/sh", "-c"]
    # caddy fronts the backend with the host-level discovery rewrite the
    # module source address needs; no upstream registry access is required.
    command: ["apk add --no-cache bash curl jq coreutils tar gzip zip caddy >/dev/null 2>&1 && bash /scripts/test-terraform-modules.sh"]
    networks:
      - e2e-test-network
    profiles: ["terraform-modules"]

  # ==========================================================================
  # PROXY + VIRTUAL REPOSITORY TESTS
  # ==========================================================================

  proxy-virtual-test:
    image: ghcr.io/artifact-keeper/ci-mirror/node:26-slim
    container_name: e2e-test-proxy-virtual
    depends_on:
      setup:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
    volumes:
      - ./scripts/native-tests:/scripts:ro
    command: ["bash", "-c", "apt-get update -qq && apt-get install -y -qq curl jq python3 python3-pip >/dev/null 2>&1 && bash /scripts/test-proxy-virtual.sh"]
    networks:
      - e2e-test-network
    profiles: ["proxy", "smoke", "all"]

  docker-proxy-test:
    image: ghcr.io/artifact-keeper/ci-mirror/alpine:3.24
    container_name: e2e-test-docker-proxy
    depends_on:
      setup:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
    volumes:
      - ./scripts/native-tests:/scripts:ro
    command: ["sh", "-c", "apk add --no-cache curl jq bash >/dev/null 2>&1 && bash /scripts/test-docker-proxy.sh"]
    networks:
      - e2e-test-network
    profiles: ["docker-proxy", "proxy", "all"]

  # ==========================================================================
  # TAG-FILTERED REPLICATION TESTS
  # ==========================================================================

  tag-replication-test:
    image: python:3.14-slim
    container_name: e2e-test-tag-replication
    depends_on:
      setup:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      API_URL: http://backend:8080
      ADMIN_USER: admin
    volumes:
      - ./scripts/native-tests:/scripts:ro
    command: ["bash", "/scripts/test-tag-replication.sh"]
    networks:
      - e2e-test-network
    profiles: ["tag-replication", "all"]

  # ==========================================================================
  # STORAGE GARBAGE COLLECTION TESTS
  # ==========================================================================

  storage-gc-test:
    image: alpine:3.24
    container_name: e2e-test-storage-gc
    depends_on:
      backend:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
    volumes:
      - ./scripts/native-tests:/scripts:ro
    command: ["sh", "-c", "apk add --no-cache bash curl jq >/dev/null 2>&1 && bash /scripts/test-storage-gc.sh"]
    networks:
      - e2e-test-network
    profiles: ["storage-gc", "all"]

  # ==========================================================================
  # RED TEAM SECURITY TESTING
  # ==========================================================================

  redteam:
    build:
      context: .
      dockerfile: docker/Dockerfile.redteam
    container_name: e2e-test-redteam
    depends_on:
      setup:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      GRPC_URL: backend:9090
      ADMIN_USER: admin
      DB_HOST: postgres
      DB_PORT: 5432
      DB_USER: registry
      DB_PASS: registry
      DB_NAME: artifact_registry
      RESULTS_DIR: /results
      # gRPC server reflection is disabled on purpose, so grpcurl needs the
      # service descriptors to invoke a method at all. Without them test 06
      # could not tell "the server refused me" from "I could not build the
      # request" and reported the refusal as a CRITICAL (#3491).
      PROTO_DIR: /protos
    volumes:
      - ./scripts/redteam:/scripts:ro
      - ./backend/proto:/protos:ro
      - redteam-results:/results
    command: ["bash", "/scripts/run-all.sh"]
    cap_add:
      - NET_RAW
    networks:
      - e2e-test-network
    profiles: ["redteam"]

  # ==========================================================================
  # CURATION POLICY TESTS
  # ==========================================================================

  mock-upstream:
    image: nginx:alpine
    container_name: e2e-test-mock-upstream
    profiles: ["curation"]
    volumes:
      - ./scripts/native-tests/fixtures/curation/nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./scripts/native-tests/fixtures/curation/rpm:/usr/share/nginx/html/rpm:ro
      - ./scripts/native-tests/fixtures/curation/deb:/usr/share/nginx/html/deb:ro
    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://localhost/rpm/repodata/repomd.xml"]
      interval: 3s
      timeout: 3s
      retries: 10
    networks:
      - e2e-test-network

  curation-test:
    image: alpine:3.24
    container_name: e2e-test-curation
    profiles: ["curation"]
    depends_on:
      setup:
        condition: service_healthy
      mock-upstream:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
      MOCK_UPSTREAM_URL: http://mock-upstream
      PGHOST: postgres
      PGPORT: "5432"
      PGDATABASE: artifact_registry
      PGUSER: registry
      PGPASSWORD: registry
    volumes:
      - ./scripts/native-tests:/scripts:ro
    entrypoint: ["sh", "-c", "apk add --no-cache curl jq postgresql-client bash > /dev/null 2>&1 && bash /scripts/test-curation.sh"]
    networks:
      - e2e-test-network

  # ==========================================================================
  # CACHE-CORRECTNESS + VIRTUAL-RESOLUTION TESTS (#1625, gate for #1611)
  #
  # Written as repros for #1600/#1595/#1562 and the immutable-vs-mutable
  # mis-caching, all since fixed, so they are now regression gates rather than
  # red-by-design repros — but they had never reached an assertion on `main`:
  # every run aborted at repo create against the SSRF guard until #3363. Still
  # do NOT add the `cache-correctness` profile to any per-PR gate (too heavy);
  # run via the cache-correctness-e2e.yml workflow_dispatch.
  #
  # NOTE (consolidation, re #1624): `cache-mock-upstream` is an ETag/counter/
  # mutation-aware Python server. The #1624 concurrency harness needs a similar
  # counter+latency mock. Once both land, consolidate into one mock-upstream
  # image with both knob-sets (this one already exposes a /__mock__/latency
  # control endpoint toward that goal).
  # ==========================================================================

  cache-mock-upstream:
    build:
      context: ./scripts/native-tests/mock-upstream
      dockerfile: Dockerfile
    image: artifact-keeper-mock-upstream:test
    container_name: e2e-test-cache-mock-upstream
    profiles: ["cache-correctness"]
    healthcheck:
      test: ["CMD", "python3", "-c", "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://localhost:9101/__mock__/health').read()==b'ok' else 1)"]
      interval: 3s
      timeout: 3s
      retries: 10
    networks:
      - e2e-test-network

  virtual-resolution-test:
    image: ghcr.io/artifact-keeper/ci-mirror/python:3.14-slim
    container_name: e2e-test-virtual-resolution
    profiles: ["cache-correctness"]
    depends_on:
      setup:
        condition: service_healthy
      cache-mock-upstream:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
      MOCK_UPSTREAM_URL: http://cache-mock-upstream:9101
    volumes:
      - ./scripts/native-tests:/scripts:ro
    command: ["bash", "-c", "apt-get update -qq && apt-get install -y -qq curl jq >/dev/null 2>&1 && bash /scripts/test-virtual-resolution.sh"]
    networks:
      - e2e-test-network

  cache-correctness-test:
    image: ghcr.io/artifact-keeper/ci-mirror/alpine:3.24
    container_name: e2e-test-cache-correctness
    profiles: ["cache-correctness"]
    depends_on:
      setup:
        condition: service_healthy
      cache-mock-upstream:
        condition: service_healthy
    # Throwaway e2e admin credential: ADMIN_PASSWORD / ADMIN_PASS, defined
    # ONCE in .env.test and nowhere else (#3490). NOT for deployment.
    env_file:
      - .env.test
    environment:
      REGISTRY_URL: http://backend:8080
      ADMIN_USER: admin
      MOCK_UPSTREAM_URL: http://cache-mock-upstream:9101
      # These MUST track the backend's compiled-in cache TTLs, which have no
      # runtime override: cache_classifier::MUTABLE_DEFAULT_TTL_SECS (300) and
      # cache_classifier::NEGATIVE_CACHE_TTL_SECS (45) in
      # backend/src/services/cache_classifier.rs. Waiting less than the real
      # TTL makes every Phase 2-4 assertion fail for a harness reason (#3950).
      # A unit test in cache_classifier.rs reads these two values back out of
      # this file so the pair cannot drift apart silently — which is why the
      # negative-cache POLL window is not set here: the script derives it as
      # NEG_TTL_WAIT_SECONDS = NEG_TTL_SECONDS + 15, because it has to poll
      # past the window rather than exactly to its edge (#3950).
      CACHE_TTL_SECONDS: "300"
      NEG_TTL_SECONDS: "45"
    volumes:
      - ./scripts/native-tests:/scripts:ro
    command: ["sh", "-c", "apk add --no-cache bash curl jq >/dev/null 2>&1 && bash /scripts/test-proxy-cache-correctness.sh"]
    networks:
      - e2e-test-network

networks:
  e2e-test-network:
    name: e2e-test-network
    driver: bridge

volumes:
  pki-data:
  maven-cache:
  go-cache:
  trivy-cache:
  redteam-results: