1
0
mirror of https://github.com/owncloud/ocis.git synced 2026-10-23 23:29:02 +03:00
Files
ocis/tests/acceptance/run-cs3api.py
Thomas Müller d47bb3a99b ci: eliminate per-job oCIS rebuilds via pre-built binary artifact (#12393)
* docs: add design spec for eliminating redundant Stat on WebDAV GET

Performance investigation showed every download pays an extra Stat
gRPC round-trip that upload does not. This spec describes moving the
directory/processing guards into InitiateFileDownload via a new
lightweight StatForDownload FS interface method.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>

* ci: build oCIS with ENABLE_VIPS, build ociswrapper, upload artifact from build-and-test

Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>

* ci: add NEEDRESTART comment and if-no-files-found guard to upload step

Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>

* ci: skip oCIS rebuild in runner scripts when binary already present

Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>

* ci: remove Go/Node build toolchain from api test jobs, use pre-built artifact

Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>

* ci: remove Go toolchain from smoke/protocol jobs, add libvips runtime and artifact download

Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>

* ci: remove Go toolchain and asset generation from e2e jobs, use pre-built artifact

Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>

* ci: fix libvips runtime package name (libvips42t64 for Ubuntu 24.04) and update stale comments

Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>

* chore: remove docs/superpowers (gitignored)

Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>

---------

Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 08:06:15 +02:00

144 lines
4.6 KiB
Python

#!/usr/bin/env python3
"""
Run CS3 API validator tests locally and in GitHub Actions CI.
Usage: python3 tests/acceptance/run-cs3api.py
"""
import os
import shutil
import signal
import subprocess
import sys
import time
from pathlib import Path
# ---------------------------------------------------------------------------
# Constants
# ---------------------------------------------------------------------------
# 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/ci/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"
if not ocis_bin.exists():
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/ci/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())