Ctrl K
ComunidadGuías…

docker-compose.test.yml

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

Archivo original ↗Preguntar a KiBot
# Its own project, deliberately. Without a name this file shared the project
# `alexclaw` with docker-compose.yml, so the two stacks shared one network, and
# the teardown that ends every test run — `docker compose ... down` — removed
# it. With production stopped that succeeded, and production's database then
# would not start: its container still pointed at a network that no longer
# existed. With production running it failed only because production was still
# attached, which is luck rather than protection.
#
# Named apart, the test stack gets alexclaw-test_default and nothing it tears
# down can reach production.
name: alexclaw-test

services:
  db-test:
    container_name: alexclaw-db-test
    image: pgvector/pgvector:pg17
    environment:
      POSTGRES_USER: alexclaw
      POSTGRES_PASSWORD: testpass
      POSTGRES_DB: alex_claw_test
      # The application role, created by the same script a fresh production
      # volume runs — so every test run also proves a fresh install works. The
      # suite connects as it, so a privilege the application lacks fails here
      # rather than there.
      DATABASE_APP_USERNAME: alexclaw_app
      DATABASE_APP_PASSWORD: apptest
    volumes:
      - ./db-init/01-app-role.sh:/docker-entrypoint-initdb.d/01-app-role.sh:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U alexclaw -d alex_claw_test"]
      interval: 3s
      timeout: 2s
      retries: 5

  test-elixir:
    container_name: alexclaw-test-elixir
    build:
      context: .
      target: test
    depends_on:
      db-test:
        condition: service_healthy
      # A real OpenBao, initialised for this run (test/alex_claw/vault_test.exs).
      openbao-test:
        condition: service_started
      openbao-test-init:
        condition: service_completed_successfully
    # The AppRole is bound to this address: one test-elixir container at a
    # time. Credo, format and other side work run in `tools`.
    networks:
      default: {}
      vault:
        ipv4_address: 10.213.64.10
    volumes:
      - ./.openbao-test/bootstrap:/run/alexclaw/openbao:ro
    environment:
      MIX_ENV: test
      DATABASE_USERNAME: alexclaw_app
      DATABASE_PASSWORD: apptest
      # The owner, for creating and migrating only — see the ecto.* aliases.
      DATABASE_OWNER_USERNAME: alexclaw
      DATABASE_OWNER_PASSWORD: testpass
      DATABASE_HOSTNAME: db-test
      DATABASE_NAME: alex_claw_test
      SECRET_KEY_BASE: test_secret_key_base_that_is_at_least_64_bytes_long_for_phoenix_to_accept_it

  # The test image, for Credo, mix format and other work beside a suite run:
  # no database, no OpenBao, not on the vault network.
  tools:
    build:
      context: .
      target: test
    environment:
      MIX_ENV: test

  # The same OpenBao as production, hardened the same way. Its data is a tmpfs:
  # every run starts an empty server, initialised by openbao-test-init.
  openbao-test:
    image: openbao/openbao:2.6.3@sha256:a60afafda36337abe833c4a63894bf1095098f29abea4091e7e555a33dd52889
    user: "100:1000"
    read_only: true
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    command: ["server", "-config=/openbao/config/config.hcl"]
    environment:
      SKIP_CHOWN: "1"
      BAO_API_ADDR: https://openbao-test:8200
      BAO_CLUSTER_ADDR: https://openbao-test:8201
    tmpfs:
      - /openbao/file:uid=100,gid=1000,mode=0700
    volumes:
      - ./openbao/config.hcl:/openbao/config/config.hcl:ro
      - ./.openbao-test/tls:/openbao/tls:ro
      # A fixed test key, committed: it seals nothing but this run's data.
      - ./test/fixtures/openbao/unseal:/openbao/unseal:ro
    networks:
      vault:
        ipv4_address: 10.213.64.2
    depends_on:
      openbao-test-init:
        condition: service_healthy

  # openbao-init, unattended: certificates, initialisation, AppRole, bootstrap
  # files — rewritten every run.
  openbao-test-init:
    build:
      context: ./openbao
      dockerfile: init.Dockerfile
    read_only: true
    tmpfs:
      - /tmp
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - FOWNER
    security_opt:
      - no-new-privileges:true
    environment:
      OPENBAO_ADDR: https://openbao-test:8200
      OPENBAO_HOSTNAME: openbao-test
      ALEXCLAW_ADDRESS: 10.213.64.10
      BACKUP_ADDRESS: 10.213.64.11
      OPENBAO_INIT_UNATTENDED: "1"
    volumes:
      - ./.openbao-test/tls:/openbao/tls
      - ./.openbao-test/bootstrap:/bootstrap
      - ./.openbao-test/backup:/backup-credentials
    networks:
      - vault
    healthcheck:
      test: ["CMD", "test", "-f", "/tmp/ready"]
      interval: 1s
      timeout: 2s
      retries: 60

  # Runs under the production sidecar's constraints (test/compose_hardening_test.exs),
  # so the suite — real Chromium included — proves the browser works that way.
  # The test dependencies are in the image's `test` stage, pinned.
  test-python:
    build:
      context: ./web-automator
      target: test
    entrypoint: ["sh", "-c"]
    command: ["cd /app && python -m pytest tests/ -v -p no:cacheprovider"]
    working_dir: /app
    user: "10001:10001"
    read_only: true
    tmpfs:
      - /tmp:size=512m,mode=1777
    cap_drop:
      - ALL
    security_opt:
      - "no-new-privileges:true"
    environment:
      PYTHONDONTWRITEBYTECODE: "1"
    volumes:
      - ./web-automator/tests:/app/tests

# A subnet of its own: production's vault network is 10.213.63.0/24, and two
# networks with one subnet cannot exist on one host.
networks:
  vault:
    internal: true
    ipam:
      config:
        - subnet: 10.213.64.0/24
          # Automatic addresses (the init service) from the upper half, away
          # from the pinned ones.
          ip_range: 10.213.64.128/25