Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Integration Tests
#
# Runs end-to-end integration tests using docker compose.
# Spins up an OCI registry, HTTP server, seeds test artifacts,
# and runs the integration test suite in a container.
#
# Triggered on pushes and PRs to master and development when
# relevant files change. Skipped if integration tests do not
# exist on the branch (e.g., master before they are ported).

name: Integration Tests

on:
push:
paths:
- "productmd/**"
- "tests/**"
- "pyproject.toml"
- ".github/workflows/integration.yml"
pull_request:
paths:
- "productmd/**"
- "tests/**"
- "pyproject.toml"
- ".github/workflows/integration.yml"

concurrency:
group: integration-${{ github.ref }}
cancel-in-progress: true

jobs:
integration:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Run integration tests
if: ${{ hashFiles('tests/integration/run.sh') != '' }}
run: ./tests/integration/run.sh
2 changes: 1 addition & 1 deletion tests/integration/Containerfile.registry
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM fedora:41 AS certs
FROM fedora:44 AS certs

RUN dnf install -y --setopt=install_weak_deps=False openssl && dnf clean all
RUN set -e && \
Expand Down
6 changes: 4 additions & 2 deletions tests/integration/Containerfile.registry-seed
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
ARG REGISTRY_IMAGE=localhost/integration_registry
FROM ghcr.io/oras-project/oras:v1.2.0 AS oras
FROM ${REGISTRY_IMAGE} AS registry-certs

FROM fedora:43
FROM fedora:44

COPY --from=oras /bin/oras /usr/local/bin/oras
COPY --from=localhost/integration_registry /certs/ca.crt /certs/ca.crt
COPY --from=registry-certs /certs/ca.crt /certs/ca.crt
RUN dnf install -y --setopt=install_weak_deps=False curl && dnf clean all

ENV SSL_CERT_FILE=/certs/ca.crt
Expand Down
4 changes: 3 additions & 1 deletion tests/integration/Containerfile.test-runner
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ARG REGISTRY_IMAGE=localhost/integration_registry
FROM ${REGISTRY_IMAGE} AS registry-certs
FROM python:3.11-slim

LABEL description="Integration test runner for productmd CLI tools"
Expand All @@ -7,7 +9,7 @@ WORKDIR /app
# Copy the test CA cert from the registry image (generated at build time).
# ENV vars for trusting it are set AFTER pip install so they don't break
# pip's connection to PyPI during the build.
COPY --from=localhost/integration_registry /certs/ca.crt /certs/ca.crt
COPY --from=registry-certs /certs/ca.crt /certs/ca.crt

# Install productmd with OCI extra and test dependencies
COPY . /app/
Expand Down
25 changes: 20 additions & 5 deletions tests/integration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ End-to-end tests for the `productmd` CLI tools using containerized services.

## Prerequisites

- `podman` and `podman-compose`
- `podman` with `podman-compose` or `podman compose`, **or** `docker` with `docker compose`
- Network access to pull container images (`nginx:alpine`, `python:3.11-slim`,
`ghcr.io/oras-project/oras:v1.2.0`, `fedora:43`, `registry:2`)

Expand All @@ -18,8 +18,10 @@ End-to-end tests for the `productmd` CLI tools using containerized services.
| **test-runner** | Custom (`Containerfile.test-runner`) | Waits for all services, then runs pytest |

The registry generates TLS certificates in a multi-stage build. Other
containers get the CA cert via `COPY --from=localhost/integration_registry`.
The `run.sh` script builds the registry image first.
containers get the CA cert via a configurable `REGISTRY_IMAGE` build arg
(defaults to `localhost/integration_registry` for podman, automatically
set to `integration_registry` for docker). The `run.sh` script builds
the registry image first.

## Running

Expand All @@ -29,7 +31,7 @@ The `run.sh` script builds the registry image first.
./tests/integration/run.sh
```

### Manual
### Manual (podman)

```bash
cd tests/integration
Expand All @@ -41,6 +43,19 @@ podman-compose run --rm test-runner
podman-compose down -v
```

### Manual (docker)

```bash
cd tests/integration
export REGISTRY_IMAGE=integration_registry
docker compose build registry
docker compose build registry-seed test-runner
docker compose up -d registry httpserver registry-seed
docker compose logs -f registry-seed # wait for seed
docker compose run --rm test-runner
docker compose down -v
```

## Test Fixtures

`fixtures/compose/` contains a minimal v1.2 compose with fake artifacts
Expand All @@ -66,5 +81,5 @@ addopts = "--ignore=tests/integration"
curl http://localhost:8080/metadata/images.json | python3 -m json.tool
curl -sk https://localhost:5000/v2/_catalog
curl http://localhost:8080/oci-metadata/images-oci.json | python3 -m json.tool
podman-compose logs registry-seed
podman-compose logs registry-seed # or: docker compose logs registry-seed
```
6 changes: 5 additions & 1 deletion tests/integration/compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ services:
ports:
- "8080:80"
volumes:
- ./fixtures/compose:/usr/share/nginx/html:ro,z
- ./fixtures/compose:/usr/share/nginx/html:z
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro,z
- generated-metadata:/usr/share/nginx/html/oci-metadata:ro

Expand All @@ -29,6 +29,8 @@ services:
build:
context: .
dockerfile: Containerfile.registry-seed
args:
REGISTRY_IMAGE: ${REGISTRY_IMAGE:-localhost/integration_registry}
depends_on:
- registry
restart: "no"
Expand All @@ -42,6 +44,8 @@ services:
build:
context: ../..
dockerfile: tests/integration/Containerfile.test-runner
args:
REGISTRY_IMAGE: ${REGISTRY_IMAGE:-localhost/integration_registry}
environment:
HTTP_BASE_URL: "http://httpserver:80"
REGISTRY_URL: "registry:5000"
Expand Down
13 changes: 10 additions & 3 deletions tests/integration/run.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
# Run productmd integration tests using container compose.
#
# Supports podman-compose, podman compose.
# Supports podman-compose, podman compose, and docker compose.
# Starts an HTTP server, TLS-enabled OCI registry, seeds the registry with
# test artifacts, and runs the integration test suite.
#
Expand All @@ -21,14 +21,21 @@ set -e

cd "$(dirname "$0")"

# Get podman compose comand
# Get container compose command.
# Check podman-compose (standalone) first, then docker compose,
# then podman compose (which may delegate to docker compose and
# fail if the Docker daemon is not running).
if command -v podman-compose &> /dev/null; then
COMPOSE="podman-compose"
elif command -v docker &> /dev/null && docker compose version &> /dev/null 2>&1; then
COMPOSE="docker compose"
# Docker does not use the localhost/ prefix for local images
export REGISTRY_IMAGE="integration_registry"
elif command -v podman &> /dev/null && podman compose version &> /dev/null 2>&1; then
COMPOSE="podman compose"
else
echo "Error: No container compose tool found."
echo "Install one of: podman-compose, podman compose"
echo "Install one of: podman-compose, docker compose, podman compose"
exit 1
fi

Expand Down
Loading