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
81 changes: 74 additions & 7 deletions .github/workflows/acceptance-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
- apiGraph
- apiGraphGroup
# spaces & dav
# - apiSpaces
- apiSpaces
- apiSpacesShares
- apiSpacesDavOperation
- apiDownloads
Expand Down Expand Up @@ -113,21 +113,27 @@ jobs:
# - apiCollaboration
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version-file: go.mod
cache: true


- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "24"

- name: Enable pnpm
run: corepack enable && corepack prepare pnpm@10.28.1 --activate

- name: Install libcurl 8.12.0 from source
run: |
sudo apt-get update -qq
sudo apt-get install -y libssl-dev libnghttp2-dev libpsl-dev libldap-dev libssh-dev zlib1g-dev
sudo apt-get install -y libssl-dev libnghttp2-dev libpsl-dev libldap-dev libssh-dev zlib1g-dev libvips-dev
cd /tmp
curl -sLO https://curl.se/download/curl-8.12.0.tar.gz
tar xzf curl-8.12.0.tar.gz
cd curl-8.12.0
./configure --with-ssl --with-zlib --with-nghttp2 --prefix=/usr/local --silent
./configure --with-ssl --with-zlib --with-nghttp2 --prefix=/usr/local --enable-versioned-symbols --silent
make -j$(nproc) --silent
sudo make install --silent
sudo ldconfig
Expand All @@ -150,6 +156,38 @@ jobs:
- name: Run ${{ matrix.suite }}
run: BEHAT_SUITES=${{ matrix.suite }} python3 tests/acceptance/run-github.py

cli-tests:
needs: [build-and-test]
name: ${{ matrix.suite }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
suite:
- cliCommands,apiServiceAvailability # grouped like drone; needs ClamAV + email
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version-file: go.mod
cache: true

- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "24"

- name: Enable pnpm
run: corepack enable && corepack prepare pnpm@10.28.1 --activate

- uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # 2.37.0
with:
php-version: "8.4"
extensions: curl, xml, mbstring, zip
tools: composer

- name: Run ${{ matrix.suite }}
run: BEHAT_SUITES="${{ matrix.suite }}" python3 tests/acceptance/run-github.py

core-api-tests:
name: ${{ matrix.suite }}
needs: [build-and-test]
Expand All @@ -169,7 +207,36 @@ jobs:
go-version-file: go.mod
cache: true

- uses: shivammathur/setup-php@v2
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "24"

- name: Enable pnpm
run: corepack enable && corepack prepare pnpm@10.28.1 --activate

- name: Install libcurl 8.12.0 from source
run: |
sudo apt-get update -qq
sudo apt-get install -y libssl-dev libnghttp2-dev libpsl-dev libldap-dev libssh-dev zlib1g-dev libvips-dev
cd /tmp
curl -sLO https://curl.se/download/curl-8.12.0.tar.gz
tar xzf curl-8.12.0.tar.gz
cd curl-8.12.0
./configure --with-ssl --with-zlib --with-nghttp2 --prefix=/usr/local --enable-versioned-symbols --silent
make -j$(nproc) --silent
sudo make install --silent
sudo ldconfig
curl --version | head -1
php -r '
$v = curl_version()["version"];
echo "PHP curl: $v\n";
if (version_compare($v, "8.12.0", "<")) {
fwrite(STDERR, "FATAL: PHP sees libcurl $v, need >= 8.12.0\n");
exit(1);
}
'

- uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # 2.37.0
with:
php-version: "8.4"
extensions: curl, xml, mbstring, zip
Expand All @@ -190,7 +257,7 @@ jobs:
path: tests/acceptance/output/

all-acceptance-tests:
needs: [local-api-tests]
needs: [local-api-tests, cli-tests, core-api-tests]
runs-on: ubuntu-latest
if: always()
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/weekly_pipeline_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
container: golang:1.25-alpine
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Run CI Reporter
working-directory: tools/ci-reporter
Expand Down
135 changes: 129 additions & 6 deletions tests/acceptance/run-github.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
Usage: BEHAT_SUITES=apiGraph python3 tests/acceptance/run-github.py
"""

import json
import os
import sys
import subprocess
Expand Down Expand Up @@ -113,6 +114,7 @@
"OCM_OCM_INVITE_MANAGER_INSECURE": "true",
"OCM_OCM_SHARE_PROVIDER_INSECURE": "true",
"OCM_OCM_STORAGE_PROVIDER_INSECURE": "true",
"OCM_OCM_PROVIDER_AUTHORIZER_PROVIDERS_FILE": "", # set at runtime
"NOTIFICATIONS_SMTP_HOST": EMAIL_SMTP_HOST,
"NOTIFICATIONS_SMTP_PORT": EMAIL_SMTP_PORT,
"NOTIFICATIONS_SMTP_INSECURE": "true",
Expand Down Expand Up @@ -191,7 +193,6 @@ def base_server_env(repo_root: Path, ocis_url: str, ocis_config_dir: str) -> dic
"OCIS_CONFIG_DIR": ocis_config_dir,
"STORAGE_USERS_DRIVER": "ocis",
"PROXY_ENABLE_BASIC_AUTH": "true",
"OCIS_EXCLUDE_RUN_SERVICES": "idp",
"OCIS_LOG_LEVEL": "error",
"IDM_CREATE_DEMO_USERS": "true",
"IDM_ADMIN_PASSWORD": "admin",
Expand Down Expand Up @@ -310,12 +311,23 @@ def main() -> int:
ocis_url = "https://localhost:9200"
ocis_config_dir = Path.home() / ".ocis/config"

ocis_fed_url = "https://localhost:10200"

cfg = merged_config(suites)
print(f"Suites: {suites}")
print(f"Services: email={cfg['emailNeeded']} tika={cfg['tikaNeeded']} antivirus={cfg['antivirusNeeded']}")

# build
run(["make", "-C", str(repo_root / "ocis"), "build"])
print(f"Services: email={cfg['emailNeeded']} tika={cfg['tikaNeeded']} "
f"antivirus={cfg['antivirusNeeded']} federation={cfg['federationServer']} "
f"wopi={cfg['collaborationServiceNeeded']}")

# generate IDP web assets (required for IDP service to start; matches drone ci-node-generate)
run(["make", "-C", str(repo_root / "services/idp"), "ci-node-generate"])

# build (ENABLE_VIPS=true when libvips-dev is installed, matching drone)
build_env = {}
if subprocess.run(["pkg-config", "--exists", "vips"],
capture_output=True).returncode == 0:
build_env["ENABLE_VIPS"] = "true"
run(["make", "-C", str(repo_root / "ocis"), "build"], env=build_env)
run(["make", "-C", str(repo_root / "tests/ociswrapper"), "build"],
env={"GOWORK": "off"})

Expand Down Expand Up @@ -351,19 +363,47 @@ def main() -> int:
wait_for(tika_healthy, 120, "tika")
print("tika ready.")

# OCM federation: rewrite providers.json with localhost URLs
if cfg["federationServer"]:
providers_src = repo_root / "tests/config/drone/providers.json"
providers = json.loads(providers_src.read_text())
for p in providers:
# replace container DNS names with localhost
p["domain"] = p["domain"].replace("ocis-server:9200", "localhost:9200")
p["domain"] = p["domain"].replace("federation-ocis-server:10200", "localhost:10200")
for svc in p.get("services", []):
ep = svc.get("endpoint", {})
ep["path"] = ep.get("path", "").replace("ocis-server:9200", "localhost:9200")
ep["path"] = ep.get("path", "").replace("federation-ocis-server:10200", "localhost:10200")
svc["host"] = svc.get("host", "").replace("ocis-server:9200", "localhost:9200")
svc["host"] = svc.get("host", "").replace("federation-ocis-server:10200", "localhost:10200")
providers_tmp = tempfile.NamedTemporaryFile(
mode="w", suffix=".json", prefix="ocm-providers-", delete=False)
json.dump(providers, providers_tmp)
providers_tmp.close()
cfg["extraServerEnvironment"]["OCM_OCM_PROVIDER_AUTHORIZER_PROVIDERS_FILE"] = providers_tmp.name

# init ocis
run([str(ocis_bin), "init", "--insecure", "true"])
shutil.copy(
repo_root / "tests/config/drone/app-registry.yaml",
ocis_config_dir / "app-registry.yaml",
)

# generate fontsMap.json with correct font path (drone hardcodes /drone/src/...)
font_path = str(repo_root / "tests/config/drone/NotoSans.ttf")
fontmap_tmp = tempfile.NamedTemporaryFile(
mode="w", suffix=".json", prefix="fontsMap-", delete=False)
json.dump({"defaultFont": font_path}, fontmap_tmp)
fontmap_tmp.close()

# assemble ocis server env
server_env = {**os.environ}
server_env.update(base_server_env(repo_root, ocis_url, str(ocis_config_dir)))
server_env["THUMBNAILS_TXT_FONTMAP_FILE"] = fontmap_tmp.name
server_env.update(cfg["extraServerEnvironment"])

# start ociswrapper
# start ociswrapper (primary ocis)
print("Starting ocis...")
wrapper_proc = subprocess.Popen(
[str(wrapper_bin), "serve",
Expand All @@ -375,6 +415,83 @@ def main() -> int:
)
procs.append(wrapper_proc)

# start federation ocis server (second instance on port 10200)
if cfg["federationServer"]:
fed_config_dir = Path.home() / ".ocis-federation/config"
fed_config_dir.mkdir(parents=True, exist_ok=True)
fed_data_dir = Path.home() / ".ocis-federation"

fed_env = {**os.environ}
fed_env.update(base_server_env(repo_root, ocis_fed_url, str(fed_config_dir)))
fed_env.update(cfg["extraServerEnvironment"])
fed_env.update({
"OCIS_URL": ocis_fed_url,
"PROXY_HTTP_ADDR": "0.0.0.0:10200",
"OCIS_BASE_DATA_PATH": str(fed_data_dir),
# use different ports to avoid conflicts with primary
"GATEWAY_GRPC_ADDR": "0.0.0.0:10142",
"NATS_NATS_PORT": "10233",
"NATS_NATS_HOST": "0.0.0.0",
})

# init federation ocis with separate config
run([str(ocis_bin), "init", "--insecure", "true",
"--config-path", str(fed_config_dir)])
shutil.copy(
repo_root / "tests/config/drone/app-registry.yaml",
fed_config_dir / "app-registry.yaml",
)

print("Starting federation ocis...")
fed_proc = subprocess.Popen(
[str(ocis_bin), "server"],
env=fed_env,
)
procs.append(fed_proc)

# start collaboration services (fakeoffice WOPI)
if cfg["collaborationServiceNeeded"]:
# fakeoffice: serves hosting-discovery.xml
discovery_xml = repo_root / "tests/config/drone/hosting-discovery.xml"
if discovery_xml.exists():
print("Starting fakeoffice...")
run(["docker", "run", "-d", "--name", "fakeoffice", "--network", "host",
"-v", f"{discovery_xml}:/discovery.xml:ro",
"python:3-alpine",
"sh", "-c",
"pip install flask && python -c \""
"from flask import Flask; app = Flask(__name__)\n"
"@app.route('/hosting/discovery')\n"
"def discovery(): return open('/discovery.xml').read(), 200, {'Content-Type': 'text/xml'}\n"
"app.run(host='0.0.0.0', port=8080)\""])

# wopi-fakeoffice collaboration service
wopi_env = {
**os.environ,
"OCIS_URL": ocis_url,
"MICRO_REGISTRY": "nats-js-kv",
"MICRO_REGISTRY_ADDRESS": "localhost:9233",
"COLLABORATION_LOG_LEVEL": "debug",
"COLLABORATION_GRPC_ADDR": "0.0.0.0:9301",
"COLLABORATION_HTTP_ADDR": "0.0.0.0:9300",
"COLLABORATION_DEBUG_ADDR": "0.0.0.0:9304",
"COLLABORATION_APP_PROOF_DISABLE": "true",
"COLLABORATION_APP_INSECURE": "true",
"COLLABORATION_CS3API_DATAGATEWAY_INSECURE": "true",
"OCIS_JWT_SECRET": "some-ocis-jwt-secret",
"COLLABORATION_WOPI_SECRET": "some-wopi-secret",
"COLLABORATION_APP_NAME": "FakeOffice",
"COLLABORATION_APP_PRODUCT": "Microsoft",
"COLLABORATION_APP_ADDR": "http://localhost:8080",
"COLLABORATION_WOPI_SRC": "http://localhost:9300",
}
print("Starting wopi-fakeoffice collaboration service...")
wopi_proc = subprocess.Popen(
[str(ocis_bin), "collaboration", "server"],
env=wopi_env,
)
procs.append(wopi_proc)

def cleanup(*_):
for p in procs:
try:
Expand All @@ -389,6 +506,10 @@ def cleanup(*_):
wait_for(lambda: ocis_healthy(ocis_url), 300, "ocis")
print("ocis ready.")

if cfg["federationServer"]:
wait_for(lambda: ocis_healthy(ocis_fed_url), 300, "federation ocis")
print("federation ocis ready.")

# expected failures file
if acceptance_test_type == "core-api":
filter_tags = "~@skipOnGraph&&~@skipOnOcis-OCIS-Storage"
Expand All @@ -415,6 +536,7 @@ def cleanup(*_):
behat_env = {
**os.environ,
"TEST_SERVER_URL": ocis_url,
"TEST_SERVER_FED_URL": ocis_fed_url,
"OCIS_WRAPPER_URL": "http://localhost:5200",
"BEHAT_SUITES": behat_suites_raw,
"ACCEPTANCE_TEST_TYPE": acceptance_test_type,
Expand All @@ -424,6 +546,7 @@ def cleanup(*_):
"UPLOAD_DELETE_WAIT_TIME": "0",
"EMAIL_HOST": "localhost",
"EMAIL_PORT": EMAIL_PORT,
"COLLABORATION_SERVICE_URL": "http://localhost:9300",
}
behat_env.update(cfg["extraEnvironment"])

Expand Down
Loading