Repository navigation
Acceptance Tests K8S #1045
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Acceptance Tests K8S | |
| on: | |
| pull_request: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "0 1 * * *" | |
| env: | |
| PHP_VERSION: "8.4" | |
| K3D_VERSION: "v5.8.3" | |
| HELM_VERSION: "v3.18.4" | |
| TEST_SERVER_URL: https://ocis-server | |
| STORAGE_DRIVER: ocis | |
| OCIS_WRAPPER_URL: http://localhost:5200 | |
| K8S: true | |
| jobs: | |
| api-tests: | |
| name: ${{ matrix.suite }}-k8s | |
| runs-on: ubuntu-26.04 | |
| timeout-minutes: 120 | |
| if: >- | |
| github.event_name == 'schedule' || | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'pull_request' && | |
| contains(github.event.pull_request.title || '', 'k8s')) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - suite: apiContract | |
| - suite: apiLocks | |
| - suite: apiSettings | |
| - suite: apiNotification | |
| - suite: apiCors | |
| - suite: apiGraphUser | |
| - suite: apiGraph | |
| - suite: apiGraphGroup | |
| # - suite: apiSpaces | |
| - suite: apiSpacesShares | |
| - suite: apiSpacesDavOperation | |
| - suite: apiDownloads | |
| - suite: apiAsyncUpload | |
| - suite: apiDepthInfinity | |
| - suite: apiArchiver | |
| - suite: apiActivities | |
| - suite: apiSearch1 | |
| - suite: apiSearch2 | |
| # - suite: apiSearchContent | |
| - suite: apiSharingNgShares | |
| - suite: apiReshare | |
| - suite: apiSharingNgPermissions | |
| - suite: apiSharingNgAdditionalShareRole | |
| - suite: apiSharingNgDriveInvitation | |
| # - suite: apiSharingNgItemInvitation | |
| - suite: apiSharingNgDriveLinkShare | |
| - suite: apiSharingNgItemLinkShare | |
| - suite: apiSharingNgLinkShareManagement | |
| - suite: apiAuthApp | |
| - suite: apiAntivirus | |
| - suite: apiOcm | |
| # - suite: apiCollaboration | |
| - suite: apiVault | |
| - suite: "coreApiAuth,coreApiCapabilities,coreApiFavorites,coreApiMain,coreApiVersions" | |
| - suite: "coreApiShareManagementBasicToShares,coreApiShareManagementToShares" | |
| - suite: "coreApiSharees" | |
| - suite: "coreApiSharePublicLink2" | |
| - suite: "coreApiShareOperationsToShares1,coreApiShareOperationsToShares2,coreApiSharePublicLink1,coreApiShareCreateSpecialToShares1,coreApiShareCreateSpecialToShares2,coreApiShareUpdateToShares" | |
| - suite: "coreApiTrashbin,coreApiTrashbinRestore,coreApiWebdavEtagPropagation1,coreApiWebdavEtagPropagation2" | |
| - suite: "coreApiWebdavDelete,coreApiWebdavOperations,coreApiWebdavMove2" | |
| - suite: "coreApiWebdavProperties" | |
| # - suite: "coreApiWebdavPreviews" | |
| - suite: "coreApiWebdavMove1,coreApiWebdavUpload,coreApiWebdavUploadTUS" | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Setup PHP ${{ env.PHP_VERSION }} | |
| uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0 | |
| with: | |
| php-version: ${{ env.PHP_VERSION }} | |
| extensions: curl, xml, mbstring, zip, ldap, gd | |
| tools: composer | |
| - name: Download k3d | |
| run: | | |
| curl -L \ | |
| -o k3d \ | |
| https://github.com/k3d-io/k3d/releases/download/${{ env.K3D_VERSION }}/k3d-linux-amd64 | |
| echo "dbaa79a76ace7f4ca230a1ff41dc7d8a5036a8ad0309e9c54f9bf3836dbe853e k3d" | sha256sum --check | |
| chmod +x k3d | |
| sudo mv k3d /usr/local/bin/ | |
| k3d version | |
| - name: Install Helm | |
| run: | | |
| curl -fsSL -o helm-${{ env.HELM_VERSION }}-linux-amd64.tar.gz https://get.helm.sh/helm-${{ env.HELM_VERSION }}-linux-amd64.tar.gz | |
| tar -zxvf helm-${{ env.HELM_VERSION }}-linux-amd64.tar.gz | |
| sudo mv linux-amd64/helm /usr/local/bin/helm | |
| helm version --short | |
| - name: Prepare hosts | |
| run: | | |
| echo "127.0.0.1 ocis-server clamav email collabora onlyoffice fakeoffice tika federation-ocis-server keycloak" \ | |
| | sudo tee -a /etc/hosts | |
| - name: Spin up K3d Cluster | |
| run: make -C tests/config/k8s create-cluster | |
| - name: Prepare Helm Charts | |
| env: | |
| ENABLE_ANTIVIRUS: ${{ matrix.suite == 'apiAntivirus' }} | |
| ENABLE_EMAIL: ${{ matrix.suite == 'apiNotification' || matrix.suite == 'apiSettings' || matrix.suite == 'apiOcm' }} | |
| ENABLE_TIKA: ${{ matrix.suite == 'apiSearchContent' || matrix.suite == 'apiVault' }} | |
| ENABLE_WOPI: ${{ matrix.suite == 'apiCollaboration' }} | |
| ENABLE_OCM: ${{ matrix.suite == 'apiOcm' }} | |
| ENABLE_AUTH_APP: ${{ matrix.suite == 'apiAuthApp' }} | |
| ENABLE_VAULT: ${{ matrix.suite == 'apiVault' }} | |
| run: | | |
| cd tests/config/k8s | |
| make prepare-charts | |
| if [[ "${{ matrix.suite }}" == "apiOcm" ]]; then | |
| OCM=true make prepare-charts | |
| fi | |
| # Keycloak/postgres (and the other suite-specific backends) must be up and | |
| # exposed to the cluster before oCIS is deployed: the proxy validates the | |
| # OCIS_OIDC_ISSUER well-known endpoint against Keycloak at startup in vault mode, | |
| # so `helm install --wait` would time out waiting for the proxy pod otherwise. | |
| - name: Deploy Suite-Specific External Backends | |
| run: | | |
| if [[ "${{ matrix.suite }}" == "apiNotification" || \ | |
| "${{ matrix.suite }}" == "apiSettings" || \ | |
| "${{ matrix.suite }}" == "apiOcm" ]]; then | |
| docker run -d \ | |
| -p 1025:1025 \ | |
| -p 8025:8025 \ | |
| --name mailpit \ | |
| axllent/mailpit:v1.22.3 | |
| bash tests/config/k8s/expose-external-svc.sh email:1025 | |
| fi | |
| if [[ "${{ matrix.suite }}" == "apiAntivirus" ]]; then | |
| docker run -d \ | |
| -p 3310:3310 \ | |
| --name clamav \ | |
| owncloudci/clamavd | |
| bash tests/config/k8s/expose-external-svc.sh clamav:3310 | |
| fi | |
| if [[ "${{ matrix.suite }}" == "apiSearchContent" || "${{ matrix.suite }}" == "apiVault" ]]; then | |
| docker run -d \ | |
| -p 9998:9998 \ | |
| --name tika \ | |
| apache/tika:3.2.2.0-full | |
| bash tests/config/k8s/expose-external-svc.sh tika:9998 | |
| fi | |
| if [[ "${{ matrix.suite }}" == "apiVault" ]]; then | |
| # GitHub runners ship PostgreSQL pre-installed on 5432, but not always | |
| # already running - reuse it for keycloak's DB instead of running our | |
| # own container for it, once it's up. | |
| sudo systemctl start postgresql | |
| for i in {1..30}; do | |
| sudo -u postgres pg_isready && break | |
| echo "Waiting for postgres... ($i/30)" | |
| sleep 2 | |
| done | |
| sudo -u postgres psql -c "CREATE USER keycloak WITH PASSWORD 'keycloak';" | |
| sudo -u postgres psql -c "CREATE DATABASE keycloak OWNER keycloak;" | |
| mkdir -p keycloak-certs | |
| openssl req -x509 -newkey rsa:2048 \ | |
| -keyout keycloak-certs/keycloakkey.pem \ | |
| -out keycloak-certs/keycloakcrt.pem \ | |
| -nodes -days 365 -subj "/CN=keycloak" | |
| chmod 777 keycloak-certs/* | |
| # patch the realm so the "web" client's redirect/origin URLs match | |
| # the k8s ingress domain instead of the non-k8s "localhost:9200" one | |
| sed 's|https://localhost:9200|https://ocis-server|g' \ | |
| tests/config/ci/ocis-mfa-ci-realm.dist.json > /tmp/ocis-realm.json | |
| docker run -d --name keycloak --network host \ | |
| -e OCIS_DOMAIN=https://ocis-server \ | |
| -e KC_HOSTNAME=keycloak \ | |
| -e KC_PORT=8443 \ | |
| -e KC_DB=postgres \ | |
| -e KC_DB_URL=jdbc:postgresql://localhost:5432/keycloak \ | |
| -e KC_DB_USERNAME=keycloak \ | |
| -e KC_DB_PASSWORD=keycloak \ | |
| -e KC_FEATURES=impersonation \ | |
| -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \ | |
| -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \ | |
| -e KC_HTTPS_CERTIFICATE_FILE=/keycloak-certs/keycloakcrt.pem \ | |
| -e KC_HTTPS_CERTIFICATE_KEY_FILE=/keycloak-certs/keycloakkey.pem \ | |
| -v "$(pwd)/keycloak-certs:/keycloak-certs:ro" \ | |
| -v /tmp/ocis-realm.json:/opt/keycloak/data/import/ocis-mfa-ci-realm.dist.json:ro \ | |
| quay.io/keycloak/keycloak:26.5.6 \ | |
| start-dev --proxy-headers xforwarded \ | |
| --spi-connections-http-client-default-disable-trust-manager=true \ | |
| --import-realm --health-enabled=true | |
| for i in {1..60}; do | |
| curl -skf https://localhost:9000/health/ready && break | |
| echo "Waiting for keycloak... ($i/60)" | |
| sleep 5 | |
| done | |
| bash tests/config/k8s/expose-external-svc.sh keycloak:8443 | |
| fi | |
| - name: Deploy oCIS | |
| run: | | |
| cd tests/config/k8s | |
| kubectl get pods -n ocis-server -Aw & | |
| make deploy-ocis | |
| if [[ "${{ matrix.suite }}" == "apiOcm" ]]; then | |
| OCM=true make deploy-ocis | |
| fi | |
| - name: Wait for oCIS to be ready | |
| env: | |
| FILE_URL: ${{ env.TEST_SERVER_URL }}/remote.php/dav/files/admin/hello1.txt | |
| run: | | |
| kubectl wait \ | |
| --namespace ocis-server \ | |
| --for=condition=Available \ | |
| deployment \ | |
| --all \ | |
| --timeout=10m | |
| kubectl wait \ | |
| --namespace ocis-server \ | |
| --for=condition=Ready \ | |
| pod \ | |
| --all \ | |
| --timeout=10m | |
| kubectl get pods -n ocis-server | |
| retry() { | |
| local label=$1 | |
| shift | |
| for i in {1..30}; do | |
| if "$@"; then | |
| echo "$label succeeded" | |
| return 0 | |
| fi | |
| echo "$label attempt $i failed, retrying in 10s..." | |
| sleep 10 | |
| done | |
| echo "$label failed after 30 attempts" | |
| return 1 | |
| } | |
| if [[ "${{ matrix.suite }}" == "apiVault" ]]; then | |
| # In vault mode IDM_CREATE_DEMO_USERS=false, so there is no "admin" | |
| # LDAP user to authenticate the basic-auth check below against. | |
| # Poll the proxy's unauthenticated debug readyz endpoint instead, | |
| # reached via port-forward since it isn't exposed by any Service. | |
| # local port 19205 (not 9205): 9100-9399 is already bound on the | |
| # host by the k3d loadbalancer's NodePort range, see create-cluster. | |
| kubectl -n ocis-server port-forward deployment/proxy 19205:9205 & | |
| PORT_FORWARD_PID=$! | |
| trap 'kill $PORT_FORWARD_PID 2>/dev/null' EXIT | |
| proxy_ready() { | |
| curl -sf http://localhost:19205/readyz > /dev/null | |
| } | |
| retry "proxy readyz" proxy_ready || exit 1 | |
| else | |
| echo "Creating test file in oCIS..." | |
| request() { | |
| local method=$1 | |
| shift | |
| curl -ks -o /dev/null -w "%{http_code}" \ | |
| -X "$method" \ | |
| -u admin:admin \ | |
| "$@" \ | |
| "$FILE_URL" | |
| } | |
| put_file() { | |
| request PUT \ | |
| -H "Content-Type: text/plain" \ | |
| --data "Hello from GitHub Actions!" | |
| } | |
| delete_file() { | |
| request DELETE | |
| } | |
| check_status() { | |
| local expected=$1 | |
| shift | |
| status=$("$@") | |
| [ "$status" = "$expected" ] | |
| } | |
| echo "Creating test file..." | |
| retry "create file (HTTP 201)" check_status 201 put_file || exit 1 | |
| echo "Deleting test file..." | |
| retry "delete file (HTTP 204)" check_status 204 delete_file || exit 1 | |
| fi | |
| - name: Expose debug ports | |
| run: bash tests/config/k8s/expose-debug-svc.sh | |
| # unauthenticated /readyz endpoint after config-triggered restarts. Port 9205 is unavailable | |
| # on the runner (k3d reserves 9100-9399), so expose it on 19205 for the rest of the job. | |
| # Keep the forward running since env-config scenarios may restart oCIS. The reconnect loop | |
| # recreates it after proxy pod restarts, unlike a one-off port-forward tied to a specific pod. | |
| - name: Expose proxy readyz | |
| if: matrix.suite == 'apiVault' | |
| run: | | |
| ( | |
| while true; do | |
| kubectl -n ocis-server port-forward deployment/proxy 19205:9205 >> /tmp/proxy-readyz-portforward.log 2>&1 | |
| sleep 1 | |
| done | |
| ) & | |
| - name: Build ociswrapper | |
| run: make -C tests/ociswrapper/ | |
| - name: Start ociswrapper | |
| run: | | |
| tests/ociswrapper/bin/ociswrapper serve \ | |
| --url ${{ env.TEST_SERVER_URL }} \ | |
| --admin-username admin \ | |
| --admin-password admin \ | |
| --skip-ocis-run \ | |
| -n ocis-server & | |
| - name: Prepare expected failures | |
| if: startsWith( matrix.suite, 'core' ) | |
| env: | |
| EXPECTED_FAILURES_FILE: tests/acceptance/expected-failures-API-on-OCIS-storage.md | |
| WITH_REMOTE_PHP: "false" | |
| run: | | |
| if [[ "$WITH_REMOTE_PHP" != "true" ]]; then | |
| cat tests/acceptance/expected-failures-without-remotephp.md >> \ | |
| "$EXPECTED_FAILURES_FILE" | |
| fi | |
| - name: Run API ${{ matrix.suite }} tests | |
| if: startsWith( matrix.suite, 'api' ) | |
| env: | |
| TEST_SERVER_URL: ${{ env.TEST_SERVER_URL }} | |
| TEST_SERVER_FED_URL: https://federation-ocis-server | |
| STORAGE_DRIVER: ${{ env.STORAGE_DRIVER }} | |
| BEHAT_SUITES: ${{ matrix.suite }} | |
| BEHAT_FILTER_TAGS: "~@skip&&~@skipOnGraph&&~@skipOnOcis-OCIS-Storage" | |
| EXPECTED_FAILURES_FILE: tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md | |
| OCIS_WRAPPER_URL: ${{ env.OCIS_WRAPPER_URL }} | |
| COLLABORATION_SERVICE_URL: http://ocis-server:9304 | |
| K8S: ${{ env.K8S }} | |
| KEYCLOAK: ${{ matrix.suite == 'apiVault' }} | |
| KC_URL: https://keycloak:8443 | |
| PROXY_READYZ_URL: ${{ matrix.suite == 'apiVault' && 'http://localhost:19205/readyz' || '' }} | |
| run: make test-acceptance-api | |
| - name: Run Core ${{ matrix.suite }} tests | |
| if: startsWith( matrix.suite, 'core' ) | |
| env: | |
| TEST_SERVER_URL: ${{ env.TEST_SERVER_URL }} | |
| OCIS_REVA_DATA_ROOT: "" | |
| STORAGE_DRIVER: ocis | |
| BEHAT_FILTER_TAGS: "~@skip&&~@skipOnGraph&&~@skipOnOcis-OCIS-Storage" | |
| BEHAT_SUITES: ${{ matrix.suite }} | |
| ACCEPTANCE_TEST_TYPE: core-api | |
| EXPECTED_FAILURES_FILE: tests/acceptance/expected-failures-API-on-OCIS-storage.md | |
| UPLOAD_DELETE_WAIT_TIME: "0" | |
| OCIS_WRAPPER_URL: ${{ env.OCIS_WRAPPER_URL }} | |
| WITH_REMOTE_PHP: "false" | |
| K8S: ${{ env.K8S }} | |
| run: make test-acceptance-api |