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
54 changes: 53 additions & 1 deletion .github/workflows/acceptance-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,60 @@ jobs:
name: test-logs-${{ matrix.suite }}
path: tests/acceptance/output/

litmus:
name: litmus
needs: [build-and-test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Run litmus
run: python3 tests/acceptance/run-litmus.py

cs3api:
name: cs3api
needs: [build-and-test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Run cs3api validator
run: python3 tests/acceptance/run-cs3api.py

wopi-builtin:
name: wopi-builtin
needs: [build-and-test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Run WOPI validator (builtin)
run: python3 tests/acceptance/run-wopi.py --type builtin

wopi-cs3:
name: wopi-cs3
needs: [build-and-test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Run WOPI validator (cs3)
run: python3 tests/acceptance/run-wopi.py --type cs3

all-acceptance-tests:
needs: [local-api-tests, cli-tests, core-api-tests]
needs: [local-api-tests, cli-tests, core-api-tests, litmus, cs3api, wopi-builtin, wopi-cs3]
runs-on: ubuntu-latest
if: always()
steps:
Expand Down
143 changes: 143 additions & 0 deletions tests/acceptance/run-cs3api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#!/usr/bin/env python3
"""
Run CS3 API validator tests locally and in GitHub Actions CI.

Config sourced from .drone.star cs3ApiTests() — single source of truth.
Usage: python3 tests/acceptance/run-cs3api.py
"""

import os
import shutil
import signal
import subprocess
import sys
import time
from pathlib import Path

# ---------------------------------------------------------------------------
# Constants (mirroring .drone.star)
# ---------------------------------------------------------------------------

# HTTPS — matching drone: ocis init generates a self-signed cert; proxy uses TLS by default.
# Host-side curl calls use -k (insecure) to skip cert verification.
OCIS_URL = "https://127.0.0.1:9200"
CS3API_IMAGE = "owncloud/cs3api-validator:0.2.1"


def get_docker_bridge_ip() -> str:
"""Return the Docker bridge gateway IP, reachable from host and Docker containers."""
r = subprocess.run(
["docker", "network", "inspect", "bridge",
"--format", "{{range .IPAM.Config}}{{.Gateway}}{{end}}"],
capture_output=True, text=True, check=True,
)
return r.stdout.strip()


def base_server_env(repo_root: Path, ocis_config_dir: str, ocis_public_url: str) -> dict:
"""OCIS server environment matching drone ocisServer(deploy_type='cs3api_validator')."""
return {
"OCIS_URL": ocis_public_url,
"OCIS_CONFIG_DIR": ocis_config_dir,
"STORAGE_USERS_DRIVER": "ocis",
"PROXY_ENABLE_BASIC_AUTH": "true",
# No PROXY_TLS override — drone lets ocis use its default TLS (self-signed cert from init)
# IDP excluded: its static assets are absent when running as a host process
"OCIS_EXCLUDE_RUN_SERVICES": "idp",
"OCIS_LOG_LEVEL": "error",
"IDM_CREATE_DEMO_USERS": "true",
"IDM_ADMIN_PASSWORD": "admin",
"FRONTEND_SEARCH_MIN_LENGTH": "2",
"OCIS_ASYNC_UPLOADS": "true",
"OCIS_EVENTS_ENABLE_TLS": "false",
"NATS_NATS_HOST": "0.0.0.0",
"NATS_NATS_PORT": "9233",
"OCIS_JWT_SECRET": "some-ocis-jwt-secret",
"EVENTHISTORY_STORE": "memory",
"WEB_UI_CONFIG_FILE": str(repo_root / "tests/config/drone/ocis-config.json"),
# cs3api_validator extras (drone ocisServer deploy_type="cs3api_validator")
"GATEWAY_GRPC_ADDR": "0.0.0.0:9142",
"OCIS_SHARING_PUBLIC_SHARE_MUST_HAVE_PASSWORD": "false",
}


def wait_for(condition_fn, timeout: int, label: str) -> None:
deadline = time.time() + timeout
while not condition_fn():
if time.time() > deadline:
print(f"Timeout waiting for {label}", file=sys.stderr)
sys.exit(1)
time.sleep(1)


def ocis_healthy(ocis_url: str) -> bool:
r = subprocess.run(
["curl", "-sk", "-uadmin:admin",
f"{ocis_url}/graph/v1.0/users/admin",
"-w", "%{http_code}", "-o", "/dev/null"],
capture_output=True, text=True,
)
return r.stdout.strip() == "200"


def main() -> int:
repo_root = Path(__file__).resolve().parents[2]
ocis_bin = repo_root / "ocis/bin/ocis"
ocis_config_dir = Path.home() / ".ocis/config"

subprocess.run(["make", "-C", str(repo_root / "ocis"), "build"], check=True)

# Docker bridge gateway IP: reachable from both the host and Docker containers.
# cs3api-validator connects to the GRPC gateway at {bridge_ip}:9142.
bridge_ip = get_docker_bridge_ip()
print(f"Docker bridge IP: {bridge_ip}", flush=True)

server_env = {**os.environ}
server_env.update(base_server_env(repo_root, str(ocis_config_dir),
f"https://{bridge_ip}:9200"))

subprocess.run(
[str(ocis_bin), "init", "--insecure", "true"],
env=server_env,
check=True,
)
shutil.copy(
repo_root / "tests/config/drone/app-registry.yaml",
ocis_config_dir / "app-registry.yaml",
)

print("Starting ocis...", flush=True)
ocis_proc = subprocess.Popen(
[str(ocis_bin), "server"],
env=server_env,
)

def cleanup(*_):
try:
ocis_proc.terminate()
except Exception:
pass

signal.signal(signal.SIGTERM, cleanup)
signal.signal(signal.SIGINT, cleanup)

try:
wait_for(lambda: ocis_healthy(OCIS_URL), 300, "ocis")
print("ocis ready.", flush=True)

print(f"\nRunning cs3api-validator against {bridge_ip}:9142", flush=True)
result = subprocess.run(
["docker", "run", "--rm",
"--entrypoint", "/usr/bin/cs3api-validator",
CS3API_IMAGE,
"/var/lib/cs3api-validator",
f"--endpoint={bridge_ip}:9142"],
)
return result.returncode

finally:
cleanup()


if __name__ == "__main__":
sys.exit(main())
64 changes: 0 additions & 64 deletions tests/acceptance/run-github.sh

This file was deleted.

Loading
Loading