Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
127 changes: 127 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
name: integration

# Drives real editors against a real Nextcloud with this app in it. Everything
# it runs is what tests/rig/README.md describes, so a failure here can be
# reproduced with the same commands on a laptop.

on:
# branches are covered by pull_request; running both would run everything
# twice for one change and leave a cancelled run on the pull request
push:
branches: [master]
paths:
- 'lib/**'
- 'js/**'
- 'appinfo/**'
- 'tests/rig/**'
- 'Makefile'
- '.github/workflows/integration.yml'
pull_request:
workflow_dispatch:
inputs:
tests:
description: 'which tests to run (blank = all; see run_all.py --list)'
required: false
default: ''
schedule:
# the document server tree is rebuilt from upstream weekly, so a release
# that breaks the editor shows up here rather than in production
- cron: '0 4 * * 1'

permissions:
contents: read

concurrency:
# the branch name, not the ref: a push is refs/heads/x and the pull request
# whose head it is is refs/pull/n/merge, and both would otherwise run the
# whole thing
group: integration-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

jobs:
rig:
runs-on: ubuntu-latest
timeout-minutes: 90

steps:
- uses: actions/checkout@v4

- name: read the document server release out of the Makefile
id: ds
run: |
echo "repo=$(grep -m1 '^ds_repo=' Makefile | cut -d= -f2 | tr '/' '-')" >> "$GITHUB_OUTPUT"
echo "version=$(grep -m1 '^ds_version=' Makefile | cut -d= -f2)" >> "$GITHUB_OUTPUT"

- name: restore the document server
id: ds-cache
uses: actions/cache/restore@v4
with:
path: 3rdparty/onlyoffice/documentserver
key: ds-${{ steps.ds.outputs.repo }}-${{ steps.ds.outputs.version }}-${{ hashFiles('Makefile') }}

- name: build the document server
if: steps.ds-cache.outputs.cache-hit != 'true'
env:
# the release asset is resolved through the API, which is rate
# limited per IP for anonymous callers - shared with every other
# runner on the same host
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq rpm cpio jq
make 3rdparty/onlyoffice/documentserver
du -sh 3rdparty/onlyoffice/documentserver

# saved here rather than at the end of the job: the whole point of the
# cache is the quarter of an hour the build takes, and a job that fails
# its tests would otherwise throw it away and rebuild next time
- name: keep the document server for the next run
if: steps.ds-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: 3rdparty/onlyoffice/documentserver
key: ds-${{ steps.ds.outputs.repo }}-${{ steps.ds.outputs.version }}-${{ hashFiles('Makefile') }}

- name: install what drives the browser
run: |
python3 -m pip install --quiet websockets requests
# the runner image ships Chrome; the rig will take either
echo "RIG_CHROMIUM=$(command -v google-chrome || command -v chromium || command -v chromium-browser)" >> "$GITHUB_ENV"

- name: start the rig
env:
RIG_PORT: 8099
run: tests/rig/rig.sh up

- name: provision it
env:
RIG_PORT: 8099
run: tests/rig/rig.sh provision

- name: run the regression suite
env:
RIG_PORT: 8099
run: tests/rig/rig.sh test --keep-going ${{ github.event.inputs.tests }}

- name: what the app logged
if: always()
env:
RIG_PORT: 8099
run: tests/rig/rig.sh logs

- name: screenshots and reports from the failing sessions
if: failure()
uses: actions/upload-artifact@v4
with:
name: rig-output
path: |
/tmp/coedit/**
/tmp/rig-*
if-no-files-found: ignore
retention-days: 7

- name: stop the rig
if: always()
env:
RIG_PORT: 8099
run: tests/rig/rig.sh down
62 changes: 62 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: lint

on:
# branches are covered by pull_request; running both would run everything
# twice for one change and leave a cancelled run on the pull request
push:
branches: [master]
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: lint-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

jobs:
php:
name: php ${{ matrix.php }} syntax
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# what the supported Nextcloud releases run on, and what the servers
# this is deployed to actually have
php: ['8.1', '8.3', '8.4']
steps:
- uses: actions/checkout@v4

- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none

- name: lint
run: |
find lib appinfo tests -name '*.php' -not -path './3rdparty/*' -print0 \
| xargs -0 -n1 -P4 php -l

javascript:
name: javascript syntax
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: lint
run: for f in js/*.js; do node --check "$f" && echo "ok $f"; done

python:
name: rig scripts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: compile
run: python3 -m compileall -q tests/rig
- name: shellcheck
run: |
sudo apt-get update -qq && sudo apt-get install -y -qq shellcheck
shellcheck -S warning tests/rig/*.sh
102 changes: 102 additions & 0 deletions .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: phpunit

# The tests that do not need a browser: the session table, the IPC backends,
# and the decisions about when a document's change list may be thrown away.
# They talk to a real Nextcloud, so this builds one around the app.

on:
# branches are covered by pull_request; running both would run everything
# twice for one change and leave a cancelled run on the pull request
push:
branches: [master]
paths:
- 'lib/**'
- 'tests/**'
- '!tests/rig/**'
- 'appinfo/**'
- '.github/workflows/phpunit.yml'
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
# the branch name, not the ref: a push is refs/heads/x and the pull request
# whose head it is is refs/pull/n/merge, and both would otherwise run the
# whole thing
group: phpunit-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

jobs:
phpunit:
runs-on: ubuntu-latest
timeout-minutes: 30

services:
# one of the three IPC backends, and the one an instance under load
# actually uses; without it those tests only ever skip
redis:
image: redis:7
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s
--health-timeout 3s
--health-retries 10

steps:
- name: check out the server this app supports
uses: actions/checkout@v4
with:
repository: nextcloud/server
# the newest release appinfo/info.xml declares support for
ref: stable34
submodules: true
path: server

- name: check out the app into it
uses: actions/checkout@v4
with:
path: server/apps/documentserver_community

- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: apcu, bcmath, curl, gd, gmp, intl, mbstring, pdo_sqlite, redis, sqlite3, xml, zip
ini-values: apc.enable_cli=1
coverage: none
tools: composer

- name: server dependencies
working-directory: server
run: composer install --no-progress --no-interaction

- name: app dev dependencies (phpunit)
working-directory: server/apps/documentserver_community
run: composer install --no-progress --no-interaction

- name: install nextcloud
working-directory: server
run: |
mkdir -p data
php occ maintenance:install \
--database sqlite --admin-user admin --admin-pass admin --no-interaction
php occ app:enable --force documentserver_community
php occ config:system:set redis host --value 127.0.0.1
php occ config:system:set redis port --value 6379 --type integer
php occ app:list | grep -A2 documentserver

- name: run the tests
working-directory: server
# from the server root, which is where a Nextcloud test expects to be,
# with the app's own phpunit - the server keeps its dependencies in
# lib/composer and its dev tools in vendor-bin, so there is no
# vendor/bin/phpunit there to borrow
run: apps/documentserver_community/vendor/bin/phpunit -c apps/documentserver_community/tests/phpunit.xml

- name: what the server logged
if: failure()
working-directory: server
run: tail -50 data/nextcloud.log || true
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
3rdparty/onlyoffice
build
oo-extract
*.rpm
*.rpm
vendor
composer.lock
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ appstore:
--exclude="../$(app_name)/3rdparty/onlyoffice/documentserver/fonts" \
--exclude="../$(app_name)/build" \
--exclude="../$(app_name)/tests" \
--exclude="../$(app_name)/vendor" \
--exclude="../$(app_name)/composer.json" \
--exclude="../$(app_name)/composer.lock" \
--exclude="../$(app_name)/Makefile" \
--exclude="../$(app_name)/screenshots" \
--exclude="../$(app_name)/.*" \
Expand All @@ -51,7 +54,8 @@ appstore:
# one fixed filename per release, while Euro-Office puts the version in the
# filename and it does not always match the tag (the v9.3.2 release ships a
# 9.3.1-dev.1 rpm).
url=$$(curl -sfL https://api.github.com/repos/$(ds_repo)/releases/tags/$(ds_version) \
url=$$(curl -sfL $${GITHUB_TOKEN:+-H "Authorization: Bearer $$GITHUB_TOKEN"} \
https://api.github.com/repos/$(ds_repo)/releases/tags/$(ds_version) \
| grep -o 'https://[^"]*x86_64[.]rpm' | head -1); \
if [ -z "$$url" ]; then echo "no x86_64 rpm asset for $(ds_repo) $(ds_version)" >&2; exit 1; fi; \
echo "fetching $$url"; \
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ restorecon -R -v /var/www/html/nextcloud

Specific commands and paths will differ based on your specific setup.

## Tests

`tests/rig` is a disposable Nextcloud with this app in it and a set of
regression tests that drive real editors in headless chromium — they open
documents, type into them, and then ask the editor what it displays and the
saved file what it kept. See its README; the short version is:

make # once: the document server this all runs against
cd tests/rig
./rig.sh up && ./rig.sh provision
./rig.sh test

`tests/` also holds the unit tests, which run against a Nextcloud checkout:

vendor-bin/phpunit/vendor/bin/phpunit -c apps/documentserver_community/tests/phpunit.xml

Both run in CI on every push, along with php, javascript and shell linting.

## Setup from git

When installing from git `make`, `curl`, `rpm2cpio`, and `cpio` are required.
Expand Down
16 changes: 16 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "nextcloud/documentserver_community",
"description": "A document server for Nextcloud, for home users who would rather not run one",
"type": "project",
"license": "AGPL-3.0-or-later",
"config": {
"optimize-autoloader": true,
"sort-packages": true
},
"require-dev": {
"phpunit/phpunit": "^11.5"
},
"scripts": {
"test:unit": "phpunit -c tests/phpunit.xml"
}
}
Loading
Loading