Compare commits

...

34 Commits

Author SHA1 Message Date
Simon L.
6b9e68d55f fix typo
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-20 13:19:49 +01:00
Simon L.
0ed524baba modify two details in initial-setup test
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-20 13:13:09 +01:00
Simon L.
7eabc59328 adjust some details to actually do what the test is intended to do
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-20 13:08:54 +01:00
Simon L.
8ddd123568 fix removing tests from aio-interface
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-20 12:45:05 +01:00
Simon L.
b1f2d6f691 increase to 10.9.0
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-20 12:42:03 +01:00
Simon L.
2cc4c6813f Merge pull request #6178 from nextcloud/enh/noid/test-file
nextcloud-entrypoint: output error message if touch failed
2025-03-20 12:41:04 +01:00
Simon L.
91ca184262 Merge pull request #6196 from nextcloud/enh/noid/update-nc-30.0.8
nextcloud: update to 30.0.8
2025-03-20 12:37:37 +01:00
Simon L.
6d1f1c1aeb nextcloud: update to 30.0.8
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-20 12:36:57 +01:00
Simon L.
f876b23c0b develop.md: add note how to run E2EE tests
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-20 12:23:33 +01:00
Simon L.
d6446d5f03 Merge pull request #6189 from nextcloud/test/e2e-tests
aio-interface: add e2e tests via playwright
2025-03-20 12:14:24 +01:00
Simon L.
c1b60f9a51 Dockerfile: remove tests subfolder
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-20 12:12:57 +01:00
Richard Steinmetz
e37611a759 test: add e2e tests via playwright
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
2025-03-20 12:08:32 +01:00
Simon L.
4f68d3ed1c Merge pull request #6195 from nextcloud/test/more-ids
test: add more ids for e2e tests
2025-03-20 10:56:11 +01:00
Simon L.
43f73ccbfe Merge pull request #6194 from nextcloud/dependabot/docker/Containers/talk/nats-2.11.0-scratch
build(deps): bump nats from 2.10.26-scratch to 2.11.0-scratch in /Containers/talk
2025-03-20 10:55:03 +01:00
Simon L.
a4aa1baf54 update OO
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-20 10:54:34 +01:00
Richard Steinmetz
38254f76ab test: add more ids for e2e tests
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
2025-03-20 10:52:38 +01:00
dependabot[bot]
80ae736633 build(deps): bump nats in /Containers/talk
Bumps nats from 2.10.26-scratch to 2.11.0-scratch.

---
updated-dependencies:
- dependency-name: nats
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-20 04:31:25 +00:00
Simon L.
0e0dc0da6f Merge pull request #6172 from nextcloud/dependabot/docker/Containers/nextcloud/php-8.3.19-fpm-alpine3.21
build(deps): bump php from 8.3.17-fpm-alpine3.21 to 8.3.19-fpm-alpine3.21 in /Containers/nextcloud
2025-03-19 15:31:52 +01:00
Simon L.
4e922c0943 Merge pull request #6171 from nextcloud/dependabot/docker/Containers/mastercontainer/php-8.3.19-fpm-alpine3.21
build(deps): bump php from 8.3.17-fpm-alpine3.21 to 8.3.19-fpm-alpine3.21 in /Containers/mastercontainer
2025-03-19 15:31:43 +01:00
Simon L.
1fbc3074dd Merge pull request #6167 from nextcloud/enh/noid/stalwart
Change stalwart tag
2025-03-19 15:31:33 +01:00
Simon L.
4cb258e7d2 Merge pull request #6190 from nextcloud/test/e2e-prep
test: prepare for e2e tests
2025-03-19 14:48:08 +01:00
Richard Steinmetz
f90631125e test: prepare for e2e tests
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
2025-03-19 14:46:41 +01:00
Simon L.
7062b6aa90 add about info to documentation about aio section
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-18 23:44:03 +01:00
Simon L.
38a11c4624 Update config.yml
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-18 22:39:17 +01:00
Simon L.
c525f802d5 Update Bug_report.md
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-18 22:34:50 +01:00
Simon L.
c973834733 Merge pull request #6183 from nextcloud/dependabot/github_actions/dot-github/workflows/shivammathur/setup-php-2.32.0
build(deps): bump shivammathur/setup-php from 2.30.0 to 2.32.0 in /.github/workflows
2025-03-17 13:23:29 +01:00
dependabot[bot]
ccc6487877 build(deps): bump shivammathur/setup-php in /.github/workflows
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.30.0 to 2.32.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](a4e22b60bb...9e72090525)

---
updated-dependencies:
- dependency-name: shivammathur/setup-php
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 12:09:48 +00:00
Simon L.
1b6524b904 Update dependabot.yml
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-17 13:06:18 +01:00
Simon L.
47964fc16c Merge pull request #6181 from nextcloud/enh/noid/update-GA
update Github Actions to use commit hashes for 3rd party actions instead of version tags
2025-03-17 11:17:36 +01:00
Simon L.
63d9343972 update Github Actions to use commit hashes for 3rd party actions instead of version tags
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-17 11:15:23 +01:00
Simon L.
d164eea1ee nextcloud-entrypoint: output error message if touch failed
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-03-16 14:05:12 +01:00
dependabot[bot]
fbb71586e8 build(deps): bump php in /Containers/nextcloud
Bumps php from 8.3.17-fpm-alpine3.21 to 8.3.19-fpm-alpine3.21.

---
updated-dependencies:
- dependency-name: php
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-14 04:44:11 +00:00
dependabot[bot]
8fe6821038 build(deps): bump php in /Containers/mastercontainer
Bumps php from 8.3.17-fpm-alpine3.21 to 8.3.19-fpm-alpine3.21.

---
updated-dependencies:
- dependency-name: php
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-14 04:43:55 +00:00
Jean-Yves
36dc60e9d2 Update stalwart.json
Signed-off-by: Jean-Yves <7360784+docjyJ@users.noreply.github.com>
2025-03-13 17:45:35 +01:00
36 changed files with 441 additions and 40 deletions

View File

@@ -5,8 +5,10 @@ labels: 0. Needs triage
---
<!---
- Before submitting a bug report, please read through the documentation available at https://github.com/nextcloud/all-in-one#faq
- If you use Cloudflare Tunnel or Cloudflare Proxy, see https://github.com/nextcloud/all-in-one#notes-on-cloudflare-proxytunnel for known issues/limitations and workarounds.
- For issues with Collabora or Talk, make sure to follow https://github.com/nextcloud/all-in-one/discussions/1358. It may already resolve your issue and makes it easier to help you.
--->
<!--- Please fill out the whole template below -->

View File

@@ -1,5 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: 📘 Documentation on Nextcloud AIO
url: https://github.com/nextcloud/all-in-one#faq
about: Please read the docs first before submitting any report or request!
- name: ⛑️ General questions and support
url: https://help.nextcloud.com/tag/aio
about: For general questions, support and help
@@ -11,4 +14,4 @@ contact_links:
about: For questions specifically about AIO
- name: 💼 Nextcloud Enterprise
url: https://portal.nextcloud.com/
about: If you are a Nextcloud Enterprise customer, or need Professional support, so it can be resolved directly by our dedicated engineers more quickly
about: If you are a Nextcloud Enterprise customer, or need Professional support, so it can be resolved directly by our dedicated engineers more quickly

View File

@@ -1,7 +1,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
directory: ".github/workflows"
schedule:
interval: "daily"
time: "12:00"

View File

@@ -14,7 +14,7 @@ jobs:
- name: Check out code
uses: actions/checkout@v4
- name: Check spelling
uses: codespell-project/actions-codespell@v2
uses: codespell-project/actions-codespell@406322ec52dd7b488e48c1c4b82e2a8b3a1bf630 # v2
with:
check_filenames: true
check_hidden: true

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
- uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
with:
php-version: 8.3
extensions: apcu
@@ -44,7 +44,7 @@ jobs:
)"
sed -i "s|pecl install APCu.*\;|pecl install APCu-$apcu_version\;|" ./Containers/mastercontainer/Dockerfile
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
with:
commit-message: php dependency updates
signoff: true

View File

@@ -16,7 +16,7 @@ jobs:
uses: actions/checkout@v4
- name: Turnstyle
uses: softprops/turnstyle@v2
uses: softprops/turnstyle@25dcee5c3fcb84375f3a3f93a3c97ed0d42cfcdc # v2
with:
continue-after-seconds: 180
env:
@@ -32,7 +32,7 @@ jobs:
# See https://github.com/helm/chart-releaser-action/issues/6
- name: Set up Helm
uses: azure/setup-helm@v4
uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4
with:
version: v3.6.3
@@ -41,7 +41,7 @@ jobs:
helm lint ./nextcloud-aio-helm-chart
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.7.0
uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0
with:
mark_as_latest: false
charts_dir: .

View File

@@ -22,7 +22,7 @@ jobs:
sed -i "s|^ENV IMAGINARY_HASH.*$|ENV IMAGINARY_HASH=$imaginary_version|" ./Containers/imaginary/Dockerfile
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
with:
commit-message: imaginary-update automated change
signoff: true

View File

@@ -16,7 +16,7 @@ jobs:
fetch-depth: 0
- name: Install Helm
uses: azure/setup-helm@v4
uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4
with:
version: v3.11.1

View File

@@ -36,7 +36,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # v2
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none

View File

@@ -14,7 +14,7 @@ jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v5
- uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5
with:
issue-inactive-days: '14'
process-only: 'issues'

View File

@@ -85,7 +85,7 @@ jobs:
fi
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
with:
commit-message: nextcloud-update automated change
signoff: true

View File

@@ -18,7 +18,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Set up php
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
with:
php-version: 8.3
extensions: apcu

77
.github/workflows/playwright.yml vendored Normal file
View File

@@ -0,0 +1,77 @@
name: Playwright Tests
on:
workflow_dispatch:
env:
BASE_URL: https://localhost:8080
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: cd php/tests && npm ci
- name: Install Playwright Browsers
run: cd php/tests && npx playwright install --with-deps chromium
- name: Start fresh development server
run: |
docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true
docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true
docker pull nextcloud/all-in-one:develop
docker run \
-d \
--init \
--name nextcloud-aio-mastercontainer \
--restart always \
--publish 8080:8080 \
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--env SKIP_DOMAIN_VALIDATION=true \
--env APACHE_PORT=11000 \
nextcloud/all-in-one:develop
echo Waiting for 10 seconds for the development container to start ...
sleep 10
- name: Run Playwright tests for initial setup
run: cd php/tests && DEBUG=pw:api npx playwright test tests/initial-setup.spec.js
- name: Start fresh development server
run: |
docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true
docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true
docker run \
-d \
--init \
--name nextcloud-aio-mastercontainer \
--restart always \
--publish 8080:8080 \
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
--env SKIP_DOMAIN_VALIDATION=false \
--env APACHE_PORT=11000 \
nextcloud/all-in-one:develop
echo Waiting for 10 seconds for the development container to start ...
sleep 10
- name: Run Playwright tests for backup restore
run: cd php/tests && DEBUG=pw:api npx playwright test tests/restore-instance.spec.js
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: php/tests/playwright-report/
retention-days: 14
overwrite: true

View File

@@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v4
- name: Set up php
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
with:
php-version: 8.3
extensions: apcu
@@ -30,7 +30,7 @@ jobs:
continue-on-error: true
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: Update psalm baseline

View File

@@ -29,7 +29,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up php
uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # v2
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
with:
php-version: 8.3
extensions: apcu

View File

@@ -17,7 +17,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Run Shellcheck
uses: ludeeus/action-shellcheck@2.0.0
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0
with:
check_together: 'yes'
env:

View File

@@ -45,7 +45,7 @@ jobs:
sed -i "s|^ARG JANUS_VERSION=.*$|ARG JANUS_VERSION=$janus_version|" ./Containers/talk/Dockerfile
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
with:
commit-message: talk-update automated change
signoff: true

View File

@@ -27,7 +27,7 @@ jobs:
uses: actions/checkout@v4
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
with:
php-version: 8.3
extensions: apcu

View File

@@ -20,7 +20,7 @@ jobs:
sudo bash nextcloud-aio-helm-chart/update-helm.sh "$DOCKER_TAG"
fi
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
with:
commit-message: Helm Chart updates
signoff: true

View File

@@ -16,7 +16,7 @@ jobs:
run: |
sudo bash manual-install/update-yaml.sh
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
with:
commit-message: Yaml updates
signoff: true

View File

@@ -6,7 +6,7 @@ FROM docker:28.0.1-cli AS docker
FROM caddy:2.9.1-alpine AS caddy
# From https://github.com/docker-library/php/blob/master/8.3/alpine3.21/fpm/Dockerfile
FROM php:8.3.17-fpm-alpine3.21
FROM php:8.3.19-fpm-alpine3.21
EXPOSE 80
EXPOSE 8080
@@ -66,6 +66,7 @@ RUN set -ex; \
cd /var/www/docker-aio; \
git clone https://github.com/nextcloud-releases/all-in-one.git --depth 1 .; \
find ./ -maxdepth 1 -mindepth 1 -not -path ./php -not -path ./community-containers -exec rm -r {} \; ; \
rm -r ./php/tests; \
chown www-data:www-data -R /var/www/docker-aio; \
cd php; \
sudo -u www-data composer install --no-dev; \

View File

@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM php:8.3.17-fpm-alpine3.21
FROM php:8.3.19-fpm-alpine3.21
ENV PHP_MEMORY_LIMIT=512M
ENV PHP_UPLOAD_LIMIT=16G
@@ -8,7 +8,7 @@ ENV SOURCE_LOCATION=/usr/src/nextcloud
ENV REDIS_DB_INDEX=0
# AIO settings start # Do not remove or change this line!
ENV NEXTCLOUD_VERSION=30.0.7
ENV NEXTCLOUD_VERSION=30.0.8
ENV AIO_TOKEN=123456
ENV AIO_URL=localhost
# AIO settings end # Do not remove or change this line!

View File

@@ -33,7 +33,7 @@ while ! nc -z "$REDIS_HOST" "6379"; do
done
# Check permissions in ncdata
touch "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" &>/dev/null
touch "$NEXTCLOUD_DATA_DIR/this-is-a-test-file"
if ! [ -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" ]; then
echo "The www-data user doesn't seem to have access rights in the datadir.
Most likely are the files located on a drive that does not follow linux permissions.

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest
# From https://github.com/ONLYOFFICE/Docker-DocumentServer/blob/master/Dockerfile
FROM onlyoffice/documentserver:8.3.1.1
FROM onlyoffice/documentserver:8.3.2.1
# USER root is probably used

View File

@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM nats:2.10.26-scratch AS nats
FROM nats:2.11.0-scratch AS nats
FROM eturnal/eturnal:1.12.1 AS eturnal
FROM strukturag/nextcloud-spreed-signaling:2.0.2 AS signaling
FROM alpine:3.21.3 AS janus

View File

@@ -5,7 +5,7 @@
"display_name": "Stalwart",
"documentation": "https://github.com/nextcloud/all-in-one/tree/main/community-containers/stalwart",
"image": "ghcr.io/docjyj/aio-stalwart",
"image_tag": "%AIO_CHANNEL%",
"image_tag": "v3",
"internal_port": "10003",
"restart": "unless-stopped",
"ports": [

View File

@@ -27,6 +27,8 @@ Before testing, make sure that at least the amd64 containers are built successfu
There is a testing-VM available for the maintainer of AIO that allows for some final testing before releasing new version. See [this](https://cloud.nextcloud.com/apps/collectives/Nextcloud%20Handbook/Technical/AIO%20testing%20VM?fileId=6350152) for details.
Additionally, there are now E2E tests available that can be run via https://github.com/nextcloud/all-in-one/actions/workflows/playwright.yml
## How to promote builds from develop to beta
1. Verify that no job is running here: https://github.com/nextcloud-releases/all-in-one/actions/workflows/build_images.yml
2. Go to https://github.com/nextcloud-releases/all-in-one/actions/workflows/promote-to-beta.yml, click on `Run workflow`.

View File

@@ -900,7 +900,7 @@ class ConfigurationManager
}
public function shouldDomainValidationBeSkipped() : bool {
if (getenv('SKIP_DOMAIN_VALIDATION') !== false) {
if (getenv('SKIP_DOMAIN_VALIDATION') === 'true') {
return true;
}
return false;

View File

@@ -17,7 +17,7 @@
<div class="container">
<main>
<h1>Nextcloud AIO v10.8.0</h1>
<h1>Nextcloud AIO v10.9.0</h1>
{# Add 2nd tab warning #}
<script type="text/javascript" src="second-tab-warning.js"></script>
@@ -106,7 +106,7 @@
<p><strong>Please note:</strong> The domain validation is disabled so any domain will be accepted here! Make sure you do not make a typo here as you will not be able to change it afterwards!</p>
{% endif %}
<form method="POST" action="/api/configuration" class="xhr">
<input type="text" name="domain" value="{{ domain }}" placeholder="nextcloud.yourdomain.com"/>
<input type="text" id="domain" name="domain" value="{{ domain }}" placeholder="nextcloud.yourdomain.com"/>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Submit domain" />
@@ -195,9 +195,9 @@
if stored remotely; and the encryption password of the backup archive below:
</p>
<form method="POST" action="/api/configuration" class="xhr">
<label>Local backup location</label> <input type="text" name="borg_restore_host_location" value="{{borg_backup_host_location}}" placeholder="/mnt/backup"/><br>
<label>Local backup location</label> <input type="text" id="borg_restore_host_location" name="borg_restore_host_location" value="{{borg_backup_host_location}}" placeholder="/mnt/backup"/><br>
<label>Remote borg repo</label> <input type="text" name="borg_restore_remote_repo" value="{{borg_remote_repo}}" placeholder="ssh://user@host:port/path/to/repo"/><br>
<label>Borg passphrase</label> <input type="text" name="borg_restore_password" value="{{borg_restore_password}}" placeholder="encryption password"/><br>
<label>Borg passphrase</label> <input type="text" id="borg_restore_password" name="borg_restore_password" value="{{borg_restore_password}}" placeholder="encryption password"/><br>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Submit location and encryption password" />
@@ -241,9 +241,9 @@
<p>Initial Nextcloud username: <strong>admin</strong></p>
{% if hasBackupLocation %}
{# nextcloud_password needs to be duplicated due to a bug in Firefox. See https://github.com/nextcloud/all-in-one/issues/638. #}
<p>Initial Nextcloud password: <strong>{{ nextcloud_password }}</strong></p></details>
<p>Initial Nextcloud password: <strong id="initial-nextcloud-password">{{ nextcloud_password }}</strong></p></details>
{% else %}
<p>Initial Nextcloud password: <strong>{{ nextcloud_password }}</strong></p>
<p>Initial Nextcloud password: <strong id="initial-nextcloud-password">{{ nextcloud_password }}</strong></p>
{% endif %}
<p><a href="https://{{ domain }}" class="button" target="_blank">Open your Nextcloud ↗</a></p>
{% if not hasBackupLocation %}
@@ -370,7 +370,7 @@
<a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/usage/general.html#repository-urls">remote borg repo url</a>.
</p>
<form method="POST" action="/api/configuration" class="xhr">
<label>Local backup location</label> <input type="text" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
<label>Local backup location</label> <input type="text" id="borg_backup_host_location" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
<label>Remote borg repo</label> <input type="text" name="borg_remote_repo" placeholder="ssh://user@host:port/path/to/repo"/><br>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -408,7 +408,7 @@
To try again, click <strong>Create backup</strong>.
</p>
{% endif %}
<p>You may change the backup path again since the initial backup was not successful. After submitting the new value, you need to click on <strong>Create Backup</strong> to test the new value.</p>
<form method="POST" action="/api/configuration" class="xhr">
<label>Local backup location</label> <input type="text" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
@@ -433,7 +433,7 @@
<summary>Click here to reveal all backup options (including an option for automatic updates)</summary>
{% endif %}
<h3>Backup information</h3>
<p>This is your encryption password for backups: <strong>{{ borgbackup_password }}</strong></p>
<p>This is your encryption password for backups: <strong id="borg-backup-password">{{ borgbackup_password }}</strong></p>
<p>Please save this password in a safe place. You won't be able to restore from backup if you lose this password!</p>
<p>All important data from your Nextcloud AIO instance such as the database, your files and the mastercontainer's configuration files, will be backed up.</p>
<p>The backup uses a tool called <a target="_blank" href="https://github.com/borgbackup/borg#what-is-borgbackup"><strong>BorgBackup</strong></a>, a well-known server backup tool that efficiently backs up your files and encrypts them on the fly.</p>

View File

@@ -10,7 +10,7 @@
<h1>All-in-One setup</h1>
<p>The official Nextcloud installation method. Nextcloud All-in-One provides easy deployment and maintenance with most features included in this one Nextcloud instance.</p>
<p>⚠️ <strong>Please note down the passphrase to access the AIO interface and don't lose it!</strong></p>
<strong>Passphrase</strong><br/><span class="monospace">{{ password }}</span><br>
<strong>Passphrase</strong><br/><span id="initial-password" class="monospace">{{ password }}</span><br>
<a href="/" class="button" target="_blank">Open Nextcloud AIO login ↗</a>
</div>
{% endblock %}

7
php/tests/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
# Playwright
node_modules/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

97
php/tests/package-lock.json generated Normal file
View File

@@ -0,0 +1,97 @@
{
"name": "e2e",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "e2e",
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
"@playwright/test": "^1.51.1",
"@types/node": "^22.13.10"
}
},
"node_modules/@playwright/test": {
"version": "1.51.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.1.tgz",
"integrity": "sha512-nM+kEaTSAoVlXmMPH10017vn3FSiFqr/bh4fKg9vmAdMfd9SDqRZNvPSiAHADc/itWak+qPvMPZQOPwCBW7k7Q==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright": "1.51.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@types/node": {
"version": "22.13.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
"integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.20.0"
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/playwright": {
"version": "1.51.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz",
"integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.51.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
"version": "1.51.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz",
"integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
"dev": true,
"license": "MIT"
}
}
}

8
php/tests/package.json Normal file
View File

@@ -0,0 +1,8 @@
{
"name": "nextcloud-aio-mastercontainer-tests",
"version": "1.0.0",
"license": "AGPL-3.0-or-later",
"devDependencies": {
"@playwright/test": "^1.51.1"
}
}

View File

@@ -0,0 +1,29 @@
import { defineConfig, devices } from '@playwright/test'
/**
* @see https://playwright.dev/docs/test-configuration
*/
export default defineConfig({
testDir: './tests',
fullyParallel: false,
forbidOnly: !!process.env.CI,
retries: 0,
workers: 1,
reporter: [
['list'],
['html'],
],
use: {
baseURL: process.env.BASE_URL ?? 'http://localhost:8080',
trace: 'on',
},
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
ignoreHTTPSErrors: true,
},
},
],
})

View File

@@ -0,0 +1,96 @@
import { test, expect } from '@playwright/test';
import { writeFileSync } from 'node:fs'
test('Initial setup', async ({ page: setupPage }) => {
test.setTimeout(10 * 60 * 1000)
// Extract initial password
await setupPage.goto('./setup');
const password = await setupPage.locator('#initial-password').innerText()
const containersPagePromise = setupPage.waitForEvent('popup');
await setupPage.getByRole('link', { name: 'Open Nextcloud AIO login ↗' }).click();
const containersPage = await containersPagePromise;
// Log in and wait for redirect
await containersPage.locator('#master-password').click();
await containersPage.locator('#master-password').fill(password);
await containersPage.getByRole('button', { name: 'Log in' }).click();
await containersPage.waitForURL('./containers');
// Reject IP addresses
await containersPage.locator('#domain').click();
await containersPage.locator('#domain').fill('1.1.1.1');
await containersPage.getByRole('button', { name: 'Submit domain' }).click();
await expect(containersPage.locator('body')).toContainText('Please enter a domain and not an IP-address!');
// Accept example.com (requires disabled domain validation)
await containersPage.locator('#domain').click();
await containersPage.locator('#domain').fill('example.com');
await containersPage.getByRole('button', { name: 'Submit domain' }).click();
// Disable all additional containers
await containersPage.locator('#talk').uncheck();
await containersPage.getByRole('checkbox', { name: 'Whiteboard' }).uncheck();
await containersPage.getByRole('checkbox', { name: 'Imaginary' }).uncheck();
await containersPage.getByRole('checkbox', { name: 'Collabora' }).uncheck();
await containersPage.getByRole('button', { name: 'Save changes' }).click();
await expect(containersPage.locator('#talk')).not.toBeChecked()
await expect(containersPage.getByRole('checkbox', { name: 'Whiteboard' })).not.toBeChecked()
await expect(containersPage.getByRole('checkbox', { name: 'Imaginary' })).not.toBeChecked()
await expect(containersPage.getByRole('checkbox', { name: 'Collabora' })).not.toBeChecked()
// Reject invalid time zones
await containersPage.locator('#timezone').click();
await containersPage.locator('#timezone').fill('Invalid time zone');
containersPage.once('dialog', dialog => {
console.log(`Dialog message: ${dialog.message()}`)
dialog.accept()
});
await containersPage.getByRole('button', { name: 'Submit timezone' }).click();
await expect(containersPage.locator('body')).toContainText('The entered timezone does not seem to be a valid timezone!')
// Accept valid time zone
await containersPage.locator('#timezone').click();
await containersPage.locator('#timezone').fill('Europe/Berlin');
containersPage.once('dialog', dialog => {
console.log(`Dialog message: ${dialog.message()}`)
dialog.accept()
});
await containersPage.getByRole('button', { name: 'Submit timezone' }).click();
// Start containers and wait for starting message
await containersPage.getByRole('button', { name: 'Download and start containers' }).click();
await expect(containersPage.getByRole('main')).toContainText('Containers are currently starting.', { timeout: 3 * 60 * 1000 });
await expect(containersPage.getByRole('link', { name: 'Open your Nextcloud ↗' })).toBeVisible({ timeout: 2 * 60 * 1000 });
await expect(containersPage.getByRole('link', { name: 'Open your Nextcloud ↗' })).toHaveAttribute('href', 'https://example.com');
// Extract initial nextcloud password
await expect(containersPage.getByRole('main')).toContainText('Initial Nextcloud password:')
const initialNextcloudPassword = await containersPage.locator('#initial-nextcloud-password').innerText();
// Set backup location and create backup
const borgBackupLocation = `/mnt/test/aio-${Math.floor(Math.random() * 2147483647)}`
await containersPage.locator('#borg_backup_host_location').click();
await containersPage.locator('#borg_backup_host_location').fill(borgBackupLocation);
await containersPage.getByRole('button', { name: 'Submit backup location' }).click();
containersPage.once('dialog', dialog => {
console.log(`Dialog message: ${dialog.message()}`)
dialog.accept()
});
await containersPage.getByRole('button', { name: 'Create backup' }).click();
await expect(containersPage.getByRole('main')).toContainText('Backup container is currently running:', { timeout: 3 * 60 * 1000 });
await expect(containersPage.getByRole('main')).toContainText('Last backup successful on', { timeout: 3 * 60 * 1000 });
await containersPage.getByText('Click here to reveal all backup options').click();
await expect(containersPage.locator('#borg-backup-password')).toBeVisible();
const borgBackupPassword = await containersPage.locator('#borg-backup-password').innerText();
// Assert that all containers are stopped
await expect(containersPage.getByRole('button', { name: 'Start containers' })).toBeVisible();
// Save passwords for restore backup test
writeFileSync('test_data.json', JSON.stringify({
initialNextcloudPassword,
borgBackupLocation,
borgBackupPassword,
}))
});

View File

@@ -0,0 +1,79 @@
import { test, expect } from '@playwright/test';
import { readFileSync } from 'node:fs';
test('Restore instance', async ({ page: setupPage }) => {
test.setTimeout(10 * 60 * 1000)
// Load passwords from previous test
const {
initialNextcloudPassword,
borgBackupLocation,
borgBackupPassword,
} = JSON.parse(readFileSync('test_data.json'))
// Extract initial password
await setupPage.goto('./setup');
const password = await setupPage.locator('#initial-password').innerText()
const containersPagePromise = setupPage.waitForEvent('popup');
await setupPage.getByRole('link', { name: 'Open Nextcloud AIO login ↗' }).click();
const containersPage = await containersPagePromise;
// Log in and wait for redirect
await containersPage.locator('#master-password').click();
await containersPage.locator('#master-password').fill(password);
await containersPage.getByRole('button', { name: 'Log in' }).click();
await containersPage.waitForURL('./containers');
// Reject example.com (requires enabled domain validation)
await containersPage.locator('#domain').click();
await containersPage.locator('#domain').fill('example.com');
await containersPage.getByRole('button', { name: 'Submit domain' }).click();
await expect(containersPage.locator('body')).toContainText('Domain does not point to this server or the reverse proxy is not configured correctly.');
// Reject invalid backup location
await containersPage.locator('#borg_restore_host_location').click();
await containersPage.locator('#borg_restore_host_location').fill('/mnt/test/aio-incorrect-path');
await containersPage.locator('#borg_restore_password').click();
await containersPage.locator('#borg_restore_password').fill(borgBackupPassword);
await containersPage.getByRole('button', { name: 'Submit location and encryption password' }).click()
await containersPage.getByRole('button', { name: 'Test path and encryption' }).click();
await expect(containersPage.getByRole('main')).toContainText('Last test failed!', { timeout: 60 * 1000 });
// Reject invalid backup password
await containersPage.locator('#borg_restore_host_location').click();
await containersPage.locator('#borg_restore_host_location').fill(borgBackupLocation);
await containersPage.locator('#borg_restore_password').click();
await containersPage.locator('#borg_restore_password').fill('foobar');
await containersPage.getByRole('button', { name: 'Submit location and encryption password' }).click()
await containersPage.getByRole('button', { name: 'Test path and encryption' }).click();
await expect(containersPage.getByRole('main')).toContainText('Last test failed!', { timeout: 60 * 1000 });
// Accept correct backup location and password
await containersPage.locator('#borg_restore_host_location').click();
await containersPage.locator('#borg_restore_host_location').fill(borgBackupLocation);
await containersPage.locator('#borg_restore_password').click();
await containersPage.locator('#borg_restore_password').fill(borgBackupPassword);
await containersPage.getByRole('button', { name: 'Submit location and encryption password' }).click()
await containersPage.getByRole('button', { name: 'Test path and encryption' }).click();
// Check integrity and restore backup
await containersPage.getByRole('button', { name: 'Check backup integrity' }).click();
await expect(containersPage.getByRole('main')).toContainText('Last check successful!', { timeout: 5 * 60 * 1000 });
await containersPage.getByRole('button', { name: 'Restore selected backup' }).click();
await expect(containersPage.getByRole('main')).toContainText('Backup container is currently running:');
// Verify a successful backup restore
await expect(containersPage.getByRole('main')).toContainText('Last restore successful!', { timeout: 3 * 60 * 1000 });
await expect(containersPage.getByRole('main')).toContainText('⚠️ Container updates are available. Click on Stop containers and Start and update containers to update them. You should consider creating a backup first.');
containersPage.once('dialog', dialog => {
console.log(`Dialog message: ${dialog.message()}`)
dialog.accept()
});
await containersPage.getByRole('button', { name: 'Start and update containers' }).click();
await expect(containersPage.getByRole('link', { name: 'Open your Nextcloud ↗' })).toBeVisible({ timeout: 5 * 60 * 1000 });
await expect(containersPage.getByRole('main')).toContainText(initialNextcloudPassword);
// Verify that containers are all stopped
await containersPage.getByRole('button', { name: 'Stop containers' }).click();
await expect(containersPage.getByRole('button', { name: 'Start containers' })).toBeVisible({ timeout: 60 * 1000 });
});